1
1
Fork 0
Browse Source

android build

master
alistair 3 years ago
parent
commit
1d09af729e
  1. 25
      build-android/CMakeLists.txt
  2. 20
      build-android/LICENSE
  3. 56
      build-android/README.md
  4. 3
      build-android/android/.gitignore
  5. 1
      build-android/android/SDL2/.gitignore
  6. 38
      build-android/android/SDL2/build.gradle
  7. 25
      build-android/android/SDL2/proguard-rules.pro
  8. 1
      build-android/android/app/.gitignore
  9. 45
      build-android/android/app/build.gradle
  10. 25
      build-android/android/app/proguard-rules.pro
  11. 31
      build-android/android/build.gradle
  12. 17
      build-android/android/gradle.properties
  13. BIN
      build-android/android/gradle/wrapper/gradle-wrapper.jar
  14. 6
      build-android/android/gradle/wrapper/gradle-wrapper.properties
  15. 160
      build-android/android/gradlew
  16. 90
      build-android/android/gradlew.bat
  17. 4
      build-android/android/settings.gradle
  18. 17
      build-android/get_dependencies.sh
  19. BIN
      build-android/res/TerminusTTF.ttf
  20. BIN
      build-android/res/hello.png
  21. 226
      build-android/src/audio.c
  22. 37
      build-android/src/audio.h
  23. 97
      build-android/src/basic-lib.c
  24. 238
      build-android/src/colours.c
  25. 43
      build-android/src/colours.h
  26. 106
      build-android/src/controlscheme.c
  27. 35
      build-android/src/controlscheme.h
  28. 159
      build-android/src/datatypes.c
  29. 61
      build-android/src/datatypes.h
  30. 2
      build-android/src/debuginfo.h
  31. 881
      build-android/src/draw.c
  32. 42
      build-android/src/draw.h
  33. 244
      build-android/src/environment.c
  34. 12
      build-android/src/environment.h
  35. 1869
      build-android/src/game.c
  36. 82
      build-android/src/game.h
  37. 185
      build-android/src/main.c
  38. 61
      build-android/src/main.cpp
  39. 2
      build-android/src/physics.c
  40. 0
      build-android/src/physics.h
  41. 236
      build-android/src/types.h
  42. 81
      build-android/src/vect.c
  43. 45
      build-android/src/vect.h

25
build-android/CMakeLists.txt

@ -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)

20
build-android/LICENSE

@ -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.

56
build-android/README.md

@ -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

3
build-android/android/.gitignore vendored

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
distribution/
.gradle/
.idea/

1
build-android/android/SDL2/.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
.externalNativeBuild/

38
build-android/android/SDL2/build.gradle

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
apply plugin: 'com.android.library'
android {
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'
}
}
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'
}

25
build-android/android/SDL2/proguard-rules.pro vendored

@ -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

1
build-android/android/app/.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
.externalNativeBuild/

45
build-android/android/app/build.gradle

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "pvallet.com.github.hello_sdl2"
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'
}
}
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'
}

25
build-android/android/app/proguard-rules.pro vendored

@ -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

31
build-android/android/build.gradle

@ -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
}

17
build-android/android/gradle.properties

@ -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

BIN
build-android/android/gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

6
build-android/android/gradle/wrapper/gradle-wrapper.properties vendored

@ -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

160
build-android/android/gradlew vendored

@ -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 "$@"

90
build-android/android/gradlew.bat vendored

@ -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

4
build-android/android/settings.gradle

@ -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'

17
build-android/get_dependencies.sh

@ -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/

BIN
build-android/res/TerminusTTF.ttf

Binary file not shown.

BIN
build-android/res/hello.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

226
build-android/src/audio.c

@ -0,0 +1,226 @@ @@ -0,0 +1,226 @@
#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);
}
}
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_U8,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);
// 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
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;
}
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);
}

37
build-android/src/audio.h

@ -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

97
build-android/src/basic-lib.c

@ -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(&current_time); printf("%s",asctime(localtime(&current_time))); printf(string, content);}
// #define log_str(string) if (LOGGING) {time_t current_time; time(&current_time); puts(asctime(localtime(&current_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(&current_time);
copy_str(time_str, asctime(localtime(&current_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);
}

238
build-android/src/colours.c

@ -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);
}
}

43
build-android/src/colours.h

@ -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

106
build-android/src/controlscheme.c

@ -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

35
build-android/src/controlscheme.h

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
#include <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;
Uint8 mouse_attach_rope_pull;
Uint8 mouse_attach_rope;
};
extern struct InputMap input_map;
void get_input_map(void);
void save_controls(void);
#endif

159
build-android/src/datatypes.c

@ -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);
}

61
build-android/src/datatypes.h

@ -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

2
build-android/src/debuginfo.h

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
#define SHOWCOLLISIONBOX 1

881
build-android/src/draw.c

@ -0,0 +1,881 @@ @@ -0,0 +1,881 @@
#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);
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;
// 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_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);
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]);*/
/*}*/
}

42
build-android/src/draw.h

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
#ifndef _DEFDRAW
#define _DEFDRAW
#include <SDL.h>
#include <SDL_ttf.h>
#include "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(SDL_Renderer *ren, 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

244
build-android/src/environment.c

@ -0,0 +1,244 @@ @@ -0,0 +1,244 @@
#include "environment.h"
#include "game.h"
#include "types.h"
struct environment * environment_watch = NULL;
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) {
/*Vect position;*/
/*ArrayList ceil; // doubles*/
/*ArrayList floor; // doubles*/
/*ArrayList bg1; // doubles*/
/*ArrayList bg2; // doubles*/
/*struct colour_pallete colours;*/
/*struct physics_collection physics;*/
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;
if (high_contrast_mode)
return get_pallete_high_contrast();
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;
}
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);
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);
// r[0] == ceiling
// r[3] == floor
//node.y += r[0];
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);
// node.y = fmod(perlin(bit), 3000);
Vect *z = malloc(sizeof(Vect));
*z = node;
z->y = h[0];
arlst_add(&e.floor, z);
z = malloc(sizeof(Vect));
*z = node;
// z->y += r[1];
z->y = h[1];
arlst_add(&e.bg1, z);
z = malloc(sizeof(Vect));
*z = node;
//z->y += r[2];
z->y = h[2];
arlst_add(&e.bg2, z);
z = malloc(sizeof(Vect));
*z = node;
// z->y += r[3];
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;
}

12
build-android/src/environment.h

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#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);
#endif

1869
build-android/src/game.c

File diff suppressed because it is too large Load Diff

82
build-android/src/game.h

@ -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

185
build-android/src/main.c

@ -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
*/

61
build-android/src/main.cpp

@ -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;
}

2
build-android/src/physics.c

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
#include "physics.h"
#include "types.h"

0
build-android/src/physics.h

236
build-android/src/types.h

@ -0,0 +1,236 @@ @@ -0,0 +1,236 @@
#ifndef PTYPES_H
#define PTYPES_H
#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 "colours.h"
#include "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)
//float x_vel;
//float y_vel;
//float x_acc;
//float y_acc;
/*------------------*/
// 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 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 = 100000,
E_ROOM_WIDTH = 10000,
E_ROOM_RES = 500,
E_ROOM_TILES = E_ROOM_WIDTH / E_ROOM_RES,
};
#endif

81
build-android/src/vect.c

@ -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);
}

45
build-android/src/vect.h

@ -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…
Cancel
Save