diff options
Diffstat (limited to 'games/transmission')
36 files changed, 2491 insertions, 0 deletions
diff --git a/games/transmission/Makefile b/games/transmission/Makefile new file mode 100644 index 00000000..60ab1d0a --- /dev/null +++ b/games/transmission/Makefile @@ -0,0 +1,319 @@ +#************************************************************************************************** +# +# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5 +# +# Copyright (c) 2013-2018 Ramon Santamaria (@raysan5) +# +# 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. +# +#************************************************************************************************** + +.PHONY: all clean + +# Define required raylib variables +# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() +PLATFORM ?= PLATFORM_DESKTOP +RAYLIB_PATH ?= ..\.. +PROJECT_NAME ?= transmission + +# Default path for raylib on Raspberry Pi, if installed in different path, update it! +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_PATH ?= /home/pi/raylib +endif + +# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) +RAYLIB_LIBTYPE ?= STATIC + +# Use external GLFW library instead of rglfw module +USE_EXTERNAL_GLFW ?= FALSE + +# Use Wayland display server protocol on Linux desktop +# by default it uses X11 windowing system +USE_WAYLAND_DISPLAY ?= FALSE + +# NOTE: On PLATFORM_WEB OpenAL Soft backend is used by default (check raylib/src/Makefile) + + +# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + # No uname.exe on MinGW!, but OS=Windows_NT on Windows! + # ifeq ($(UNAME),Msys) -> Windows + ifeq ($(OS),Windows_NT) + PLATFORM_OS=WINDOWS + else + UNAMEOS=$(shell uname) + ifeq ($(UNAMEOS),Linux) + PLATFORM_OS=LINUX + endif + ifeq ($(UNAMEOS),FreeBSD) + PLATFORM_OS=FREEBSD + endif + ifeq ($(UNAMEOS),Darwin) + PLATFORM_OS=OSX + endif + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + UNAMEOS=$(shell uname) + ifeq ($(UNAMEOS),Linux) + PLATFORM_OS=LINUX + endif +endif + +ifeq ($(PLATFORM),PLATFORM_WEB) + # Emscripten required variables + EMSDK_PATH = C:/emsdk + EMSCRIPTEN_VERSION = 1.37.28 + CLANG_VERSION=e1.37.28_64bit + PYTHON_VERSION=2.7.5.3_64bit + NODE_VERSION=4.1.1_64bit + export PATH=$(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) + EMSCRIPTEN=$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) +endif + +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/release/libs + +# Define raylib release directory for compiled library +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),WINDOWS) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32 + endif + ifeq ($(PLATFORM_OS),LINUX) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux + endif + ifeq ($(PLATFORM_OS),OSX) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx + endif + ifeq ($(PLATFORM_OS),FREEBSD) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/freebsd + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5 +endif + +# Define default C compiler: gcc +# NOTE: define g++ compiler if using C++ +CC = gcc + +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),OSX) + # OSX default compiler + CC = clang + endif + ifeq ($(PLATFORM_OS),FREEBSD) + # FreeBSD default compiler + CC = clang + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) + # Define RPI cross-compiler + #CC = armv6j-hardfloat-linux-gnueabi-gcc + CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc + endif +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # HTML5 emscripten compiler + CC = emcc +endif + +# Define default make program: Mingw32-make +MAKE = mingw32-make + +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + MAKE = make + endif +endif + +# Define compiler flags: +# -O1 defines optimization level +# -g enable debugging +# -s strip unnecessary data from build +# -Wall turns on most, but not all, compiler warnings +# -std=c99 defines C language mode (standard C from 1999 revision) +# -std=gnu99 defines C language mode (GNU C from 1999 revision) +# -Wno-missing-braces ignore invalid warning (GCC bug 53119) +# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec +CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces + +# Additional flags for compiler (if desired) +#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),WINDOWS) + # resources file contains windows exe icon + # -Wl,--subsystem,windows hides the console window + CFLAGS += $(RAYLIB_PATH)/src/resources -Wl,--subsystem,windows + endif + ifeq ($(PLATFORM_OS),LINUX) + CFLAGS += -no-pie -D_DEFAULT_SOURCE + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + CFLAGS += -std=gnu99 +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # -O2 # if used, also set --memory-init-file 0 + # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) + # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) + # -s USE_PTHREADS=1 # multithreading support + # -s WASM=1 # support Web Assembly (https://github.com/kripken/emscripten/wiki/WebAssembly) + # --preload-file resources # specify a resources folder for data compilation + CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 --profiling --preload-file resources -s TOTAL_MEMORY=67108864 + + # Define a custom shell .html and output extension + CFLAGS += --shell-file $(RAYLIB_PATH)\templates\web_shell\shell.html + EXT = .html +endif + +# Define include paths for required headers +# NOTE: Several external required libraries (stb and others) +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external + +# Define additional directories containing required header files +ifeq ($(PLATFORM),PLATFORM_RPI) + # RPI requried libraries + INCLUDE_PATHS += -I/opt/vc/include + INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux + INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads +endif + +# Define library paths containing required libs +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src + +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),FREEBSD) + INCLUDE_PATHS += -I/usr/local/include + LDFLAGS += -L. -Lsrc -L/usr/local/lib + endif +endif + +ifeq ($(PLATFORM),PLATFORM_RPI) + LDFLAGS += -L/opt/vc/lib +endif + +# Define any libraries required on linking +# if you want to link libraries (libname.so or libname.a), use the -lname +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),WINDOWS) + # Libraries for Windows desktop compilation + LDLIBS = -lraylib -lopengl32 -lgdi32 + endif + ifeq ($(PLATFORM_OS),LINUX) + # Libraries for Debian GNU/Linux desktop compiling + # NOTE: Required packages: libegl1-mesa-dev + LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt + + # On X11 requires also below libraries + LDLIBS += -lX11 + # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them + #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor + + # On Wayland windowing system, additional libraries requires + ifeq ($(USE_WAYLAND_DISPLAY),TRUE) + LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon + endif + endif + ifeq ($(PLATFORM_OS),OSX) + # Libraries for OSX 10.9 desktop compiling + # NOTE: Required packages: libopenal-dev libegl1-mesa-dev + LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa + endif + ifeq ($(PLATFORM_OS),FREEBSD) + # Libraries for FreeBSD desktop compiling + # NOTE: Required packages: mesa-libs + LDLIBS = -lraylib -lGL -lpthread -lm + + # On XWindow requires also below libraries + LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor + endif + ifeq ($(USE_EXTERNAL_GLFW),TRUE) + # NOTE: It could require additional packages installed: libglfw3-dev + LDLIBS += -lglfw + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + # Libraries for Raspberry Pi compiling + # NOTE: Required packages: libasound2-dev (ALSA) + LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + # Libraries for web (HTML5) compiling + LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc +endif + +# Define all source files required +PROJECT_SOURCE_FILES ?= transmission.c \ + screens/screen_logo.c \ + screens/screen_title.c \ + screens/screen_mission.c \ + screens/screen_gameplay.c \ + screens/screen_ending.c + +# Define all object files from source files +OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES)) + +# For Android platform we call a custom Makefile.Android +ifeq ($(PLATFORM),PLATFORM_ANDROID) + MAKEFILE_PARAMS = -f Makefile.Android + export PROJECT_NAME + export PROJECT_SOURCE_FILES +else + MAKEFILE_PARAMS = $(PROJECT_NAME) +endif + +# Default target entry +# NOTE: We call this Makefile target or Makefile.Android target +all: + $(MAKE) $(MAKEFILE_PARAMS) + +# Project target defined by PROJECT_NAME +$(PROJECT_NAME): $(OBJS) + $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + +# Compile source files +# NOTE: This pattern will compile every module defined on $(OBJS) +%.o: %.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) + +# Clean everything +clean: +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),WINDOWS) + del *.o *.exe /s + endif + ifeq ($(PLATFORM_OS),LINUX) + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + endif + ifeq ($(PLATFORM_OS),OSX) + find . -type f -perm +ugo+x -delete + rm -f *.o + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + find . -type f -executable -delete + rm -f *.o +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + del *.o *.html *.js +endif + @echo Cleaning done + diff --git a/games/transmission/Makefile.Android b/games/transmission/Makefile.Android new file mode 100644 index 00000000..f082ab23 --- /dev/null +++ b/games/transmission/Makefile.Android @@ -0,0 +1,275 @@ +#************************************************************************************************** +# +# raylib makefile for Android project (APK building) +# +# Copyright (c) 2017 Ramon Santamaria (@raysan5) +# +# 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. +# +#************************************************************************************************** + +# Define required raylib variables +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Required path variables +# NOTE: JAVA_HOME must be set to JDK +ANDROID_HOME = C:/android-sdk +ANDROID_NDK = C:/android-ndk +ANDROID_TOOLCHAIN = C:/android_toolchain_arm_api16 +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/26.0.2 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools +JAVA_HOME = C:/PROGRA~1/Java/jdk1.8.0_144 + +# Android project configuration variables +PROJECT_NAME ?= raylib_game +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_RESOURCES_PATH ?= resources +PROJECT_SOURCE_FILES ?= raylib_game.c + +# Some source files are placed in directories, when compiling to some +# output directory other than source, that directory must pre-exist. +# Here we get a list of required folders that need to be created on +# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors. +PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES))) + +# Android app configuration variables +APP_LABEL_NAME ?= rGame +APP_COMPANY_NAME ?= raylib +APP_PRODUCT_NAME ?= rgame +APP_VERSION_CODE ?= 1 +APP_VERSION_NAME ?= 1.0 +APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png +APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png +APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png +APP_SCREEN_ORIENTATION ?= landscape +APP_KEYSTORE_PASS ?= raylib + +# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) +RAYLIB_LIBTYPE ?= STATIC +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\release\libs\android\armeabi-v7a + +# Shared libs must be added to APK if required +# NOTE: Generated NativeLoader.java automatically load those libraries +ifeq ($(RAYLIB_LIBTYPE),SHARED) + PROJECT_SHARED_LIBS = lib/armeabi-v7a/libraylib.so +endif + +# Compiler and archiver +# NOTE: GCC is being deprectated in Android NDK r16 +CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-gcc +AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar + +# Compiler flags for arquitecture +CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +# Compilation functions attributes options +CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC +# Compiler options for the linker +CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes +# Preprocessor macro definitions +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=16 + +# Paths containing required header files +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/release/include -I$(RAYLIB_PATH)/src/external/android/native_app_glue + +# Linker options +LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a +LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings +# Force linking of library module to define symbol +LDFLAGS += -u ANativeActivity_onCreate +# Library paths containing required libs +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/armeabi-v7a + +# Define any libraries to link into executable +# if you want to link libraries (libname.so or libname.a), use the -lname +LDLIBS = -lraylib -lnative_app_glue -llog -landroid -lEGL -lGLESv2 -lOpenSLES -latomic -lc -lm -ldl + +# Generate target objects list from PROJECT_SOURCE_FILES +OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) + +# Android APK building process... some steps required... +# NOTE: typing 'make' will invoke the default target entry called 'all', +all: create_temp_project_dirs \ + copy_project_required_libs \ + copy_project_resources \ + generate_loader_script \ + generate_android_manifest \ + generate_apk_keystore \ + config_project_package \ + compile_native_app_glue \ + compile_project_code \ + compile_project_class \ + compile_project_class_dex \ + create_project_apk_package \ + sign_project_apk_package \ + zipalign_project_apk_package + +# Create required temp directories for APK building +create_temp_project_dirs: + if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH) + if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj + if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src + if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com + if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) + if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) + if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib + if not exist $(PROJECT_BUILD_PATH)\lib\armeabi-v7a mkdir $(PROJECT_BUILD_PATH)\lib\armeabi-v7a + if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin + if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res + if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi + if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi + if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi + if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values + if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets + if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) + if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens + $(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir))) + +define create_dir + if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1) +endef + +# Copy required shared libs for integration into APK +# NOTE: If using shared libs they are loaded by generated NativeLoader.java +copy_project_required_libs: +ifeq ($(RAYLIB_LIBTYPE),SHARED) + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.so +endif +ifeq ($(RAYLIB_LIBTYPE),STATIC) + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\armeabi-v7a\libraylib.a +endif + +# Copy project required resources: strings.xml, icon.png, assets +# NOTE: Required strings.xml is generated and game resources are copied to assets folder +# TODO: Review xcopy usage, it can not be found in some systems! +copy_project_resources: + copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y + copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y + copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y + @echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/res/values/strings.xml + @echo ^<resources^>^<string name="app_name"^>$(APP_LABEL_NAME)^</string^>^</resources^> >> $(PROJECT_BUILD_PATH)/res/values/strings.xml + if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F + +# Generate NativeLoader.java to load required shared libraries +# NOTE: Probably not the bet way to generate this file... but it works. +generate_loader_script: + @echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java +ifeq ($(RAYLIB_LIBTYPE),SHARED) + @echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java +endif + @echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + +# Generate AndroidManifest.xml with all the required options +# NOTE: Probably not the bet way to generate this file... but it works. +generate_android_manifest: + @echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<manifest xmlns:android="http://schemas.android.com/apk/res/android" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<uses-sdk android:minSdkVersion="16" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<uses-feature android:glEsVersion="0x00020000" android:required="true" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<application android:allowBackup="false" android:label="@string/app_name" android:icon="@drawable/icon" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<activity android:name="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME).NativeLoader" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<meta-data android:name="android.app.lib_name" android:value="$(PROJECT_LIBRARY_NAME)" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<action android:name="android.intent.action.MAIN" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^<category android:name="android.intent.category.LAUNCHER" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^</intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^</activity^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^</application^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^</manifest^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + +# Generate storekey for APK signing: $(PROJECT_NAME).keystore +# NOTE: Configure here your Distinguished Names (-dname) if required! +generate_apk_keystore: + if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA + +# Config project package and resource using AndroidManifest.xml and res/values/strings.xml +# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java +config_project_package: + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-16/android.jar + +# Compile native_app_glue code as static library: obj/libnative_app_glue.a +compile_native_app_glue: + $(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS) + $(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o + +# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so +compile_project_code: $(OBJS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + +# Compile all .c files required into object (.o) files +# NOTE: Those files will be linked into a shared library +$(PROJECT_BUILD_PATH)/obj/%.o:%.c + $(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot + +# Compile project .java code into .class (Java bytecode) +compile_project_class: + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-16/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + +# Compile .class files into Dalvik executable bytecode (.dex) +# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) +compile_project_class_dex: + $(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj + +# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk +# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so +# NOTE: Use -A resources to define additional directory in which to find raw asset files +create_project_apk_package: + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-16/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/armeabi-v7a/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + +# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk +sign_project_apk_package: + $(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key + +# Create zip-aligned APK package: $(PROJECT_NAME).apk +zipalign_project_apk_package: + $(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk + +# Install $(PROJECT_NAME).apk to default emulator/device +# NOTE: Use -e (emulator) or -d (device) parameters if required +install: + $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + +# Monitorize output log coming from device, only raylib tag +logcat: + $(ANDROID_PLATFORM_TOOLS)/adb logcat -c + $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S + +# Install and monitorize $(PROJECT_NAME).apk to default emulator/device +deploy: + $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb logcat -c + $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S + +#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W + +# Clean everything +clean: + del $(PROJECT_BUILD_PATH)\* /f /s /q + rmdir $(PROJECT_BUILD_PATH) /s /q + @echo Cleaning done diff --git a/games/transmission/resources/audio/fx_batman.ogg b/games/transmission/resources/audio/fx_batman.ogg Binary files differnew file mode 100644 index 00000000..d3e25ae2 --- /dev/null +++ b/games/transmission/resources/audio/fx_batman.ogg diff --git a/games/transmission/resources/audio/fx_button.ogg b/games/transmission/resources/audio/fx_button.ogg Binary files differnew file mode 100644 index 00000000..8d0747ca --- /dev/null +++ b/games/transmission/resources/audio/fx_button.ogg diff --git a/games/transmission/resources/audio/fx_grab.ogg b/games/transmission/resources/audio/fx_grab.ogg Binary files differnew file mode 100644 index 00000000..b78e1315 --- /dev/null +++ b/games/transmission/resources/audio/fx_grab.ogg diff --git a/games/transmission/resources/audio/fx_leave.ogg b/games/transmission/resources/audio/fx_leave.ogg Binary files differnew file mode 100644 index 00000000..24abdbee --- /dev/null +++ b/games/transmission/resources/audio/fx_leave.ogg diff --git a/games/transmission/resources/audio/fx_message.ogg b/games/transmission/resources/audio/fx_message.ogg Binary files differnew file mode 100644 index 00000000..60de6655 --- /dev/null +++ b/games/transmission/resources/audio/fx_message.ogg diff --git a/games/transmission/resources/audio/fx_newspaper.ogg b/games/transmission/resources/audio/fx_newspaper.ogg Binary files differnew file mode 100644 index 00000000..bcc54841 --- /dev/null +++ b/games/transmission/resources/audio/fx_newspaper.ogg diff --git a/games/transmission/resources/audio/fx_place.ogg b/games/transmission/resources/audio/fx_place.ogg Binary files differnew file mode 100644 index 00000000..a300a968 --- /dev/null +++ b/games/transmission/resources/audio/fx_place.ogg diff --git a/games/transmission/resources/audio/fx_typing.ogg b/games/transmission/resources/audio/fx_typing.ogg Binary files differnew file mode 100644 index 00000000..89a09daf --- /dev/null +++ b/games/transmission/resources/audio/fx_typing.ogg diff --git a/games/transmission/resources/audio/music_mission.ogg b/games/transmission/resources/audio/music_mission.ogg Binary files differnew file mode 100644 index 00000000..2de719bb --- /dev/null +++ b/games/transmission/resources/audio/music_mission.ogg diff --git a/games/transmission/resources/audio/music_title.ogg b/games/transmission/resources/audio/music_title.ogg Binary files differnew file mode 100644 index 00000000..d75b1ddc --- /dev/null +++ b/games/transmission/resources/audio/music_title.ogg diff --git a/games/transmission/resources/audio/s_p_y.xm b/games/transmission/resources/audio/s_p_y.xm Binary files differnew file mode 100644 index 00000000..ebbdbf93 --- /dev/null +++ b/games/transmission/resources/audio/s_p_y.xm diff --git a/games/transmission/resources/audio/spy_versus_spy.xm b/games/transmission/resources/audio/spy_versus_spy.xm Binary files differnew file mode 100644 index 00000000..11602adc --- /dev/null +++ b/games/transmission/resources/audio/spy_versus_spy.xm diff --git a/games/transmission/resources/fonts/Lora-Bold.ttf b/games/transmission/resources/fonts/Lora-Bold.ttf Binary files differnew file mode 100644 index 00000000..e48c4262 --- /dev/null +++ b/games/transmission/resources/fonts/Lora-Bold.ttf diff --git a/games/transmission/resources/fonts/mom_typewritter.ttf b/games/transmission/resources/fonts/mom_typewritter.ttf Binary files differnew file mode 100644 index 00000000..13f5dc7d --- /dev/null +++ b/games/transmission/resources/fonts/mom_typewritter.ttf diff --git a/games/transmission/resources/fonts/traveling_typewriter.ttf b/games/transmission/resources/fonts/traveling_typewriter.ttf Binary files differnew file mode 100644 index 00000000..5d9d7c9b --- /dev/null +++ b/games/transmission/resources/fonts/traveling_typewriter.ttf diff --git a/games/transmission/resources/missions.txt b/games/transmission/resources/missions.txt new file mode 100644 index 00000000..63569608 --- /dev/null +++ b/games/transmission/resources/missions.txt @@ -0,0 +1,65 @@ +# Total missions +# NOTE: Missions follow the order of this file +t 4 +# ----------------------------------------------------------------- +# Briefing of the mission +b Se ha visto al Presidente en actitud cariƱosa con una persona que no es la Primera Dama. Una situación comprometida que definirĆ” el curso de la historia... Especialmente en campaƱa electoral y siendo del partido conservador... Ā”El pueblo debe saber! +# +# Mission keyword +k oviparo +# +# Message to be coded +# NOTE: Sensible words must be noted using @ +m El @presidente es visto en un @hotel acompaƱado de su @amante. +# +# Solution to mission +# NOTE: Provide the correct solution nums, according to above words +# WARNING: Always provide 8 values, use -1 for not used ones +# Coding Words: POLLO = 0, CONEJO, HUEVO, NIDO, AIRE, ARMARIO, AGUJERO, PLATANO, PASTEL, MERCADO, RATON, MELON +s 0 3 2 -1 -1 -1 -1 -1 +# ----------------------------------------------------------------- +# Briefing of the mission +b Se ha visto un ovni sobrevolando la ciudad, al parecer se prevee un ataque alienĆgena inminente que definirĆ” el curso de la historia... Ā”El pueblo debe saber! +# +# Mission keyword +k roedor +# +# Message to be coded +# NOTE: Sensible words must be noted using @ +m Un @ovni ha sido detectado en el @cielo del @pais . Preparaos para el ataque de un @alien. +# +# NOTE: Provide the correct solution nums, according to above words +# WARNING: Always provide 8 values, use -1 for not used ones +# Coding Words: POLLO = 0, CONEJO, HUEVO, NIDO, AIRE, ARMARIO, AGUJERO, PLATANO, PASTEL, MERCADO, RATON, MELON +s 1 6 5 10 -1 -1 -1 -1 +# ----------------------------------------------------------------- +# Briefing of the mission +b Se ha filtrado una inminente subida del precio de un producto bĆ”sico para todo el mundo: el ajo. Le evolución de su precio de mercado definirĆ” el curso de la historia... Ā”El pueblo debe saber! +# +# Mission keyword +k comida +# +# Message to be coded +# NOTE: Sensible words must be noted using @ +m Sube el @precio del @ajo. Ā”Un @desastre inminente! +# +# NOTE: Provide the correct solution nums, according to above words +# WARNING: Always provide 8 values, use -1 for not used ones +# Coding Words: POLLO = 0, CONEJO, HUEVO, NIDO, AIRE, ARMARIO, AGUJERO, PLATANO, PASTEL, MERCADO, RATON, MELON +s 9 7 2 -1 -1 -1 -1 -1 +# ----------------------------------------------------------------- +# Briefing of the mission +b Se ha visto a un famoso presentador de TV deshaciĆ©ndose del cuerpo de un rival de otra cadena. Una pĆ©rdida que definirĆ” el curso de la historia... Especialmente cuando su programa podrĆa no continuar... Ā”El pueblo debe saber! +# +# Mission keyword +k postre +# +# Message to be coded +# NOTE: Sensible words must be noted using @ +m Un @presentador se deshace del @cuerpo de su rival. Ā”Peligra el @programa del Prime Time! +# +# NOTE: Provide the correct solution nums, according to above words +# WARNING: Always provide 8 values, use -1 for not used ones +# Coding Words: POLLO = 0, CONEJO, HUEVO, NIDO, AIRE, ARMARIO, AGUJERO, PLATANO, PASTEL, MERCADO, RATON, MELON +s 7 11 8 -1 -1 -1 -1 -1 +# -----------------------------------------------------------------
\ No newline at end of file diff --git a/games/transmission/resources/textures/cw_logo.png b/games/transmission/resources/textures/cw_logo.png Binary files differnew file mode 100644 index 00000000..bc4011d8 --- /dev/null +++ b/games/transmission/resources/textures/cw_logo.png diff --git a/games/transmission/resources/textures/ending_background.png b/games/transmission/resources/textures/ending_background.png Binary files differnew file mode 100644 index 00000000..6577be63 --- /dev/null +++ b/games/transmission/resources/textures/ending_background.png diff --git a/games/transmission/resources/textures/ending_newspaper.png b/games/transmission/resources/textures/ending_newspaper.png Binary files differnew file mode 100644 index 00000000..f44e646d --- /dev/null +++ b/games/transmission/resources/textures/ending_newspaper.png diff --git a/games/transmission/resources/textures/message_background.png b/games/transmission/resources/textures/message_background.png Binary files differnew file mode 100644 index 00000000..78c00a59 --- /dev/null +++ b/games/transmission/resources/textures/message_background.png diff --git a/games/transmission/resources/textures/message_vignette.png b/games/transmission/resources/textures/message_vignette.png Binary files differnew file mode 100644 index 00000000..72234c59 --- /dev/null +++ b/games/transmission/resources/textures/message_vignette.png diff --git a/games/transmission/resources/textures/mission_background.png b/games/transmission/resources/textures/mission_background.png Binary files differnew file mode 100644 index 00000000..4efe5815 --- /dev/null +++ b/games/transmission/resources/textures/mission_background.png diff --git a/games/transmission/resources/textures/mission_backline.png b/games/transmission/resources/textures/mission_backline.png Binary files differnew file mode 100644 index 00000000..2a89d80a --- /dev/null +++ b/games/transmission/resources/textures/mission_backline.png diff --git a/games/transmission/resources/textures/mission_words.png b/games/transmission/resources/textures/mission_words.png Binary files differnew file mode 100644 index 00000000..4e4e9d93 --- /dev/null +++ b/games/transmission/resources/textures/mission_words.png diff --git a/games/transmission/resources/textures/title_background.png b/games/transmission/resources/textures/title_background.png Binary files differnew file mode 100644 index 00000000..c90d880d --- /dev/null +++ b/games/transmission/resources/textures/title_background.png diff --git a/games/transmission/resources/textures/title_ribbon.png b/games/transmission/resources/textures/title_ribbon.png Binary files differnew file mode 100644 index 00000000..1526eba1 --- /dev/null +++ b/games/transmission/resources/textures/title_ribbon.png diff --git a/games/transmission/resources/textures/words_base.png b/games/transmission/resources/textures/words_base.png Binary files differnew file mode 100644 index 00000000..a2139030 --- /dev/null +++ b/games/transmission/resources/textures/words_base.png diff --git a/games/transmission/screens/screen_ending.c b/games/transmission/screens/screen_ending.c new file mode 100644 index 00000000..e6ab3518 --- /dev/null +++ b/games/transmission/screens/screen_ending.c @@ -0,0 +1,248 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Ending Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#include "raylib.h" +#include "screens.h" + +#include <string.h> +#include <stdlib.h> + +#define MAX_TITLE_CHAR 256 +#define MAX_SUBTITLE_CHAR 256 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- +static char *codingWords[MAX_CODING_WORDS] = { + "pollo\0", + "conejo\0", + "huevo\0", + "nido\0", + "aire\0", + "armario\0", + "agujero\0", + "platano\0", + "pastel\0", + "mercado\0", + "raton\0", + "melon\0", +}; + +// Ending screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D texBackground; +static Texture2D texNewspaper; +static Texture2D texVignette; + +static Sound fxNews; + +static float rotation = 0.1f; +static float scale = 0.05f; +static int state = 0; + +static Mission *missions = NULL; + +static char headline[MAX_TITLE_CHAR] = "\0"; + +SpriteFont fontNews; + +// String (const char *) replacement function +static char *StringReplace(char *orig, char *rep, char *with); + +//---------------------------------------------------------------------------------- +// Ending Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Ending Screen Initialization logic +void InitEndingScreen(void) +{ + framesCounter = 0; + finishScreen = 0; + + rotation = 0.1f; + scale = 0.05f; + state = 0; + + texBackground = LoadTexture("resources/textures/ending_background.png"); + texVignette = LoadTexture("resources/textures/message_vignette.png"); + fxNews = LoadSound("resources/audio/fx_batman.ogg"); + + missions = LoadMissions("resources/missions.txt"); + int wordsCount = missions[currentMission].wordsCount; + + strcpy(headline, missions[currentMission].msg); // Base headline + int len = strlen(headline); + + // Remove @ from headline + // TODO: Also remove additional spaces + for (int i = 0; i < len; i++) + { + if (headline[i] == '@') headline[i] = ' '; + } + + for (int i = 0; i < wordsCount; i++) + { + if (messageWords[i].id != missions[currentMission].sols[i]) + { + // WARNING: It fails if the last sentence word has a '.' after space + char *title = StringReplace(headline, messageWords[i].text, codingWords[messageWords[i].id]); + + strcpy(headline, title); // Base headline updated + + if (title != NULL) free(title); + } + } + + TraceLog(LOG_WARNING, "Titular: %s", headline); + + // Generate newspaper with title and subtitle + Image imNewspaper = LoadImage("resources/textures/ending_newspaper.png"); + fontNews = LoadSpriteFontEx("resources/fonts/Lora-Bold.ttf", 32, 250, 0); + ImageDrawTextEx(&imNewspaper, (Vector2){ 50, 220 }, fontNews, headline, fontNews.baseSize, 0, DARKGRAY); + + texNewspaper = LoadTextureFromImage(imNewspaper); + //UnloadSpriteFont(fontNews); + UnloadImage(imNewspaper); +} + +// Ending Screen Update logic +void UpdateEndingScreen(void) +{ + framesCounter++; + + if (framesCounter == 10) PlaySound(fxNews); + + if (state == 0) + { + rotation += 18.0f; + scale += 0.0096f; + + if (scale >= 1.0f) + { + scale = 1.0f; + state = 1; + } + } + + if ((state == 1) && (IsKeyPressed(KEY_ENTER) || IsButtonPressed())) + { + currentMission++; + + if (currentMission >= totalMissions) finishScreen = 2; + else finishScreen = 1; + } +} + +// Ending Screen Draw logic +void DrawEndingScreen(void) +{ + DrawTexture(texBackground, 0, 0, WHITE); + + DrawTexturePro(texNewspaper, (Rectangle){ 0, 0, texNewspaper.width, texNewspaper.height }, + (Rectangle){ GetScreenWidth()/2, GetScreenHeight()/2, texNewspaper.width*scale, texNewspaper.height*scale }, + (Vector2){ (float)texNewspaper.width*scale/2, (float)texNewspaper.height*scale/2 }, rotation, WHITE); + + DrawTextureEx(texVignette, (Vector2){ 0, 0 }, 0.0f, 2.0f, WHITE); + + // Draw debug information + DrawTextEx(fontNews, headline, (Vector2){ 10, 10 }, fontNews.baseSize, 0, RAYWHITE); + + for (int i = 0; i < missions[currentMission].wordsCount; i++) + { + DrawText(codingWords[messageWords[i].id], 10, 60 + 30*i, 20, (messageWords[i].id == missions[currentMission].sols[i]) ? GREEN : RED); + } + + if (state == 1) DrawButton("continuar"); +} + +// Ending Screen Unload logic +void UnloadEndingScreen(void) +{ + UnloadTexture(texBackground); + UnloadTexture(texNewspaper); + UnloadTexture(texVignette); + + UnloadSound(fxNews); + free(missions); +} + +// Ending Screen should finish? +int FinishEndingScreen(void) +{ + return finishScreen; +} + +// String (const char *) replacement function +// NOTE: Internally allocated memory must be freed by the user (if return != NULL) +// https://stackoverflow.com/questions/779875/what-is-the-function-to-replace-string-in-c +static char *StringReplace(char *orig, char *rep, char *with) +{ + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // Sanity checks and initialization + if (!orig || !rep) return NULL; + + len_rep = strlen(rep); + if (len_rep == 0) return NULL; // Empty rep causes infinite loop during count + + if (!with) with = ""; // Replace with nothing if not provided + len_with = strlen(with); + + // Count the number of replacements needed + ins = orig; + for (count = 0; tmp = strstr(ins, rep); ++count) + { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep)*count + 1); + + if (!result) return NULL; // Memory could not be allocated + + // First time through the loop, all the variable are set correctly from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) + { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + + strcpy(tmp, orig); + + return result; +} diff --git a/games/transmission/screens/screen_gameplay.c b/games/transmission/screens/screen_gameplay.c new file mode 100644 index 00000000..00c451fc --- /dev/null +++ b/games/transmission/screens/screen_gameplay.c @@ -0,0 +1,423 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#include "raylib.h" +#include "screens.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +//#define MAX_CODING_WORDS 12 +//#define MAX_MISSION_WORDS 8 +#define MAX_LINE_CHAR 30 + +/* +// NOTE: Coding words are generic and the same words +// are used for all missions, +typedef enum CodingWords { + POLLO = 0, + CONEJO, + HUEVO, + NIDO, + AIRE, + ARMARIO, + AGUJERO, + COSA, + WORD, +} CodingWords; +*/ + +static char *codingWords[MAX_CODING_WORDS] = { + "pollo\0", + "conejo\0", + "huevo\0", + "nido\0", + "aire\0", + "armario\0", + "agujero\0", + "platano\0", + "pastel\0", + "mercado\0", + "raton\0", + "melon\0" +}; + +// Words to be coded or coding words +/*typedef struct Word { + int id; + Rectangle rec; + Rectangle iniRec; + bool hover; + bool picked; + char text[32]; // text +} Word;*/ + +/* +// Mission information +typedef struct Mission { + int id; + char brief[512]; // Mission briefing + char key[32]; // Mission keyword + char msg[256]; // Message to be coded + int wordsCount; // Number of words to coded + int sols[8]; // Solution code, depends on wordsCount +} Mission; +*/ +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Gameplay screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D texBackground; +static SpriteFont fontMessage; +static Texture2D texWordsAtlas; +static Texture2D texVignette; + +static Sound fxGrab; +static Sound fxPlace; +static Sound fxLeave; + +static Music musSpy; + +static Word words[MAX_CODING_WORDS] = { 0 }; + +// Hay que hacerlo global, para poder consultar el resultado desde la endingscreen +//static Word messageWords[MAX_MISSION_WORDS] = { 0 }; + +static Mission *missions = NULL; + +static bool canSend = false; + +Vector2 msgOffset = { 430, 300 }; + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Gameplay Screen Initialization logic +void InitGameplayScreen(void) +{ + framesCounter = 0; + finishScreen = 0; + + fontMessage = LoadSpriteFontEx("resources/fonts/traveling_typewriter.ttf", 30, 250, 0); + + texBackground = LoadTexture("resources/textures/message_background.png"); + texVignette = LoadTexture("resources/textures/message_vignette.png"); + + fxGrab = LoadSound("resources/audio/fx_grab.ogg"); + fxPlace = LoadSound("resources/audio/fx_place.ogg"); + fxLeave = LoadSound("resources/audio/fx_leave.ogg"); + + musSpy = LoadMusicStream("resources/audio/s_p_y.xm"); + PlayMusicStream(musSpy); + +#if defined(PLATFORM_WEB) + #define WORD_ATLAS_FROM_FILE +#endif +#if defined(WORD_ATLAS_FROM_FILE) + texWordsAtlas = LoadTexture("resources/textures/mission_words.png"); +#else + // Generate coding words atlas directly from text + Image imWordsBase = LoadImage("resources/textures/words_base.png"); + Image imWords = GenImageColor(imWordsBase.width, imWordsBase.height*MAX_CODING_WORDS, WHITE); + + for (int i = 0; i < MAX_CODING_WORDS; i++) + { + ImageDraw(&imWords, imWordsBase, + (Rectangle){ 0, 0, imWordsBase.width, imWordsBase.height }, + (Rectangle){ 0, imWordsBase.height*i, imWordsBase.width, imWordsBase.height }); + + ImageDrawTextEx(&imWords,(Vector2){ imWordsBase.width/2 - MeasureTextEx(fontMessage, codingWords[i], + fontMessage.baseSize, 0).x/2, imWordsBase.height*i }, fontMessage, codingWords[i], + fontMessage.baseSize, 0, BLACK); + } + + texWordsAtlas = LoadTextureFromImage(imWords); + + UnloadImage(imWordsBase); + UnloadImage(imWords); +#endif + + // Initialize missions + // WARNING: Some problem with imWords image generation (memory leak?) could cause + // that loading missions before/after generation breaks game, on web is the other way round... :( + missions = LoadMissions("resources/missions.txt"); + TraceLog(LOG_WARNING, "Words count %i", missions[currentMission].wordsCount); + + // Initialize coding words + for (int i = 0; i < MAX_CODING_WORDS; i++) + { + words[i].id = -1; // Not placed anywhere + + words[i].rec.x = 110 + 940*(i/(MAX_CODING_WORDS/2)); + words[i].rec.y = 200 + 60*(i%(MAX_CODING_WORDS/2)); + words[i].rec.width = 140; // texWordsAtlas.width/MAX_MISSIONS + words[i].rec.height = 35; // texWordsAtlas.height/MAX_MISSION_WORDS + words[i].iniRec = words[i].rec; + words[i].hover = false; // Mouse hover detected + words[i].picked = false; // Mouse picked + + //words[i].text = ''; //codingWords[i]; // Fill text if required... + } + + // Analize missions[currentMission].msg string for words! + int msgLen = strlen(missions[currentMission].msg); + + // Add '/' each MAX_LINE_CHAR chars + int currentLine = 1; + int i = currentLine * MAX_LINE_CHAR; + + while (i < msgLen - 1) + { + if (missions[currentMission].msg[i] == ' ') + { + missions[currentMission].msg[i] = '/'; + currentLine++; + i = currentLine*MAX_LINE_CHAR; + } + else i++; + } + + int currentWord = 0; + int offsetX = 0; + int offsetY = 0; + bool foundWord = false; + int wordInitPosX = 0; + int wordInitPosY = 0; + + // TODO: messageWords should be reseted every mission + //memcpy(messageWords, 0, sizeof(Word)*MAX_MISSION_WORDS); + + for (int i = 0; i < msgLen; i++) + { + char c = missions[currentMission].msg[i]; + if (foundWord && (c == ' ' || c == '.')) + { + foundWord = false; + + messageWords[currentWord - 1].rec.width = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), 30, 0).x; + messageWords[currentWord - 1].rec.height = fontMessage.baseSize; + + //TODO: Guardar en message + strncpy(messageWords[currentWord - 1].text, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), i - wordInitPosX); + } + + if (c == '@') // One word to change + { + foundWord = true; + missions[currentMission].msg[i] = ' '; + + offsetX = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosY, (i + 1) - wordInitPosY), 30, 0).x; + + messageWords[currentWord].rec.x = offsetX; + messageWords[currentWord].rec.y = offsetY; + + wordInitPosX = i + 1; + + currentWord++; + } + else if (c == '/') + { + missions[currentMission].msg[i] = '\n'; + wordInitPosY = i; + offsetY += (fontMessage.baseSize + fontMessage.baseSize/2); // raylib internal increment on line break... + } + } + + for (int i = 0; i < missions[currentMission].wordsCount; i++) + { + messageWords[i].id = -1; // Not required for message words, id is the array position + + // Recalculate words rectangles considering text offset on screen + messageWords[i].rec.x += msgOffset.x; + messageWords[i].rec.y += msgOffset.y; + + // Recalculate words rectangle considering new width height + messageWords[i].rec.x -= (texWordsAtlas.width - messageWords[i].rec.width)/2; + messageWords[i].rec.y -= ((texWordsAtlas.height / MAX_CODING_WORDS) - messageWords[i].rec.height)/2; + + //Recalculate width height + messageWords[i].rec.width = texWordsAtlas.width; + messageWords[i].rec.height = texWordsAtlas.height / MAX_CODING_WORDS; + + messageWords[i].hover = false; // Mouse hover detected + messageWords[i].picked = false; // Mouse picked + } +} + +// Gameplay Screen Update logic +void UpdateGameplayScreen(void) +{ + UpdateMusicStream(musSpy); + + for (int i = 0; i < MAX_CODING_WORDS; i++) + { + if (CheckCollisionPointRec(GetMousePosition(), words[i].rec)) + { + words[i].hover = true; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + words[i].picked = true; + PlaySound(fxGrab); + } + } + else words[i].hover = false; + + + if (words[i].picked) + { + for (int j = 0; j < missions[currentMission].wordsCount; j++) + { + if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec)) messageWords[j].hover = true; + else messageWords[j].hover = false; + } + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + words[i].picked = false; + + for (int j = 0; j < missions[currentMission].wordsCount; j++) + { + messageWords[j].hover = false; + + if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec)) + { + PlaySound(fxPlace); + + words[i].rec.x = messageWords[j].rec.x; + words[i].rec.y = messageWords[j].rec.y; + + if (messageWords[j].id != -1) + { + int id = messageWords[j].id; + words[id].rec = words[id].iniRec; + } + + messageWords[j].id = i; + for (int k = 0; k < missions[currentMission].wordsCount; k++) + { + if (j != k && messageWords[j].id == messageWords[k].id) + { + messageWords[k].id = -1; + break; + } + } + break; + } + else + { + PlaySound(fxLeave); + + words[i].rec = words[i].iniRec; + if (i == messageWords[j].id) messageWords[j].id = -1; + } + } + } + } + + // TODO: Move word picked with mouse + if (words[i].picked) + { + words[i].rec.x = GetMouseX() - words[i].rec.width/2; + words[i].rec.y = GetMouseY() - words[i].rec.height/2; + + // TODO: Check if label is placed in some mission word position + //if (CheckCollisionRecs(words[i].rec)) + } + else + { + //if (words[i].id != -1) + } + } + + canSend = true; + for(int j = 0; j < missions[currentMission].wordsCount; j++) + { + if(messageWords[j].id == -1) + { + canSend = false; + break; + } + } + + if (canSend && (IsKeyPressed(KEY_ENTER) || IsButtonPressed())) + { + finishScreen = true; + } +} + +// Gameplay Screen Draw logic +void DrawGameplayScreen(void) +{ + DrawTexture(texBackground, 0, 0, WHITE); + + DrawTextEx(fontMessage, missions[currentMission].msg, msgOffset, fontMessage.baseSize, 0, BLACK); + + for (int i = 0; i < missions[currentMission].wordsCount; i++) + { + Rectangle recLines = messageWords[i].rec; + DrawRectangleLines(recLines.x, recLines.y, recLines.width, recLines.height, Fade(RED, 0.35f)); + if(messageWords[i].hover) DrawRectangleRec(messageWords[i].rec, Fade(RED, 0.30f)); + DrawText(FormatText("%i", messageWords[i].id), i*25, 0, 30, RED); + } + for (int i = 0; i < MAX_CODING_WORDS; i++) + { + if (words[i].picked) DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, MAROON); + else if (words[i].hover) DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, RED); + else DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, WHITE); + } + + DrawTexturePro(texVignette, (Rectangle){0,0,texVignette.width, texVignette.height}, (Rectangle){0,0,GetScreenWidth(), GetScreenHeight()}, (Vector2){0,0}, 0, WHITE); + + if (canSend) DrawButton("enviar"); +} + +// Gameplay Screen Unload logic +void UnloadGameplayScreen(void) +{ + UnloadTexture(texBackground); + UnloadTexture(texVignette); + UnloadTexture(texWordsAtlas); + + UnloadSound(fxGrab); + UnloadSound(fxLeave); + UnloadSound(fxPlace); + + UnloadMusicStream(musSpy); + + free(missions); +} + +// Gameplay Screen should finish? +int FinishGameplayScreen(void) +{ + return finishScreen; +} diff --git a/games/transmission/screens/screen_logo.c b/games/transmission/screens/screen_logo.c new file mode 100644 index 00000000..30271ba6 --- /dev/null +++ b/games/transmission/screens/screen_logo.c @@ -0,0 +1,102 @@ +/********************************************************************************************** +* +* raylib - Advance Game template +* +* Logo Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#include "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Logo screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D logoCW; + +static float fadeValue; +static int showLogoFrames; +static bool fadeOut; + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Logo Screen Initialization logic +void InitLogoScreen(void) +{ + framesCounter = 0; + finishScreen = 0; + + logoCW = LoadTexture("resources/textures/cw_logo.png"); + + showLogoFrames = 60; + fadeValue = 0; + + fadeOut = false; +} + +// Logo Screen Update logic +void UpdateLogoScreen(void) +{ + if(!fadeOut) + { + fadeValue += 0.02f; + if(fadeValue > 1.01f) + { + fadeValue = 1.0f; + framesCounter++; + + if(framesCounter % showLogoFrames == 0) + { + fadeOut = true; + finishScreen = true; + } + } + } + + if(IsKeyPressed(KEY_ENTER)) + { + finishScreen = true; + } +} + +// Logo Screen Draw logic +void DrawLogoScreen(void) +{ + DrawTexture(logoCW, GetScreenWidth()/2 - logoCW.width/2, GetScreenHeight()/2 - logoCW.height/2, Fade(WHITE, fadeValue)); +} + +// Logo Screen Unload logic +void UnloadLogoScreen(void) +{ + UnloadTexture(logoCW); +} + +// Logo Screen should finish? +int FinishLogoScreen(void) +{ + return finishScreen; +}
\ No newline at end of file diff --git a/games/transmission/screens/screen_mission.c b/games/transmission/screens/screen_mission.c new file mode 100644 index 00000000..0f996502 --- /dev/null +++ b/games/transmission/screens/screen_mission.c @@ -0,0 +1,293 @@ +/********************************************************************************************** +* +* raylib - transmission mission +* +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#include "raylib.h" +#include "screens.h" + +#include <string.h> +#include <stdlib.h> + +#define MISSION_MAX_LENGTH 256 +#define KEYWORD_MAX_LENGTH 32 +#define MAX_LINE_CHAR 75 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Mission screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D texBackground; + +static Texture2D texBackline; //mission_backline +static Rectangle sourceRecBackLine; +static Rectangle destRecBackLine; +static float fadeBackLine; + +static Vector2 numberPosition; +static Color numberColor; + +//static char textMission[MISSION_MAX_LENGTH]; +static Vector2 missionPosition; +static int missionSize; +static Color missionColor; +static int missionLenght; +static bool missionMaxLength; +static int missionSpeed; + +//static char textKeyword[KEYWORD_MAX_LENGTH]; +static Vector2 keywordPosition; +static Color keywordColor; + +static int showMissionWaitFrames; +static int showNumberWaitFrames; +static int showKeywordWaitFrames; + +static bool startWritting; +static bool writeMission; +static bool writeNumber; +static bool writeKeyword; +static bool writeEnd; + +static bool writtingMission; + +static int blinkFrames; +static bool blinkKeyWord = true; + +static bool showButton = false; + +static Mission *missions = NULL; + +static Sound fxTransmit; +static Music musMission; + +//---------------------------------------------------------------------------------- +// Mission Screen Functions Definition +//---------------------------------------------------------------------------------- +static void WriteMissionText(); +static void EndWritting(); +static void BlinkKeyword(); + +// Mission Screen Initialization logic +void InitMissionScreen(void) +{ + framesCounter = 0; + finishScreen = 0; + + fadeButton = 0.80f; + + texBackground = LoadTexture("resources/textures/mission_background.png"); + + texBackline = LoadTexture("resources/textures/mission_backline.png"); + sourceRecBackLine = (Rectangle){0,0,GetScreenWidth(), texBackline.height}; + destRecBackLine = (Rectangle){0,0,sourceRecBackLine.width, sourceRecBackLine.height}; + fadeBackLine = 0; + + fxTransmit = LoadSound("resources/audio/fx_message.ogg"); + musMission = LoadMusicStream("resources/audio/music_mission.ogg"); + + PlayMusicStream(musMission); + + // Initialize missions + missions = LoadMissions("resources/missions.txt"); + + missionMaxLength = strlen(missions[currentMission].brief); + + // Insert line breaks every MAX_LINE_CHAR + int currentLine = 1; + int i = currentLine * MAX_LINE_CHAR; + + while (i < missionMaxLength) + { + if (missions[currentMission].brief[i] == ' ') + { + missions[currentMission].brief[i] = '\n'; + currentLine++; + i = currentLine*MAX_LINE_CHAR; + } + else i++; + } + + missionSize = 30; + missionLenght = 0; + missionSpeed = 1; + + numberColor = RAYWHITE; + missionColor = LIGHTGRAY; + keywordColor = (Color){198, 49, 60, 255}; //RED + + numberPosition = (Vector2){150, 185}; + missionPosition = (Vector2){numberPosition.x, numberPosition.y + 60}; + keywordPosition = (Vector2){missionPosition.x, missionPosition.y + MeasureTextEx(fontMission, missions[currentMission].brief, missionSize, 0).y + 60}; + + startWritting = false; + writeNumber = false; + writeMission = false; + writeKeyword = false; + writeEnd = false; + + writtingMission = false; + + showNumberWaitFrames = 30; + showMissionWaitFrames = 60; + showKeywordWaitFrames = 60; + + blinkKeyWord = true; + blinkFrames = 15; + + PlaySound(fxTransmit); +} + +// Mission Screen Update logic +void UpdateMissionScreen(void) +{ + UpdateMusicStream(musMission); + + if (!writeEnd) WriteMissionText(); + else BlinkKeyword(); + + if (showButton) + { + if (IsKeyPressed(KEY_ENTER) || IsButtonPressed()) + { + if (!writeEnd) EndWritting(); + else + { + finishScreen = true; + showButton = false; + } + } + } +} + +// Mission Screen Draw logic +void DrawMissionScreen(void) +{ + // TODO: Draw MISSION screen here! + DrawTexture(texBackground, 0,0, WHITE); + DrawTexturePro(texBackline, sourceRecBackLine, destRecBackLine, (Vector2){0,0},0, Fade(WHITE, fadeBackLine)); + + if (writeNumber) DrawTextEx(fontMission, FormatText("Filtración #%02i ", currentMission + 1), numberPosition, missionSize + 10, 0, numberColor); + DrawTextEx(fontMission, SubText(missions[currentMission].brief, 0, missionLenght), missionPosition, missionSize, 0, missionColor); + if (writeKeyword && blinkKeyWord) DrawTextEx(fontMission, FormatText("Keyword: %s", missions[currentMission].key), keywordPosition, missionSize + 10, 0, keywordColor); + + if (showButton) + { + if (!writeEnd) DrawButton("saltar"); + else DrawButton("codificar"); + } +} + +// Mission Screen Unload logic +void UnloadMissionScreen(void) +{ + // TODO: Unload MISSION screen variables here! + UnloadTexture(texBackground); + UnloadTexture(texBackline); + UnloadSound(fxTransmit); + UnloadMusicStream(musMission); + free(missions); +} + +// Mission Screen should finish? +int FinishMissionScreen(void) +{ + return finishScreen; +} + +static void WriteMissionText() +{ + if(!startWritting) + { + framesCounter++; + if(framesCounter % 60 == 0) + { + framesCounter = 0; + startWritting = true; + } + } + else if(!writeNumber) + { + framesCounter++; + fadeBackLine += 0.020f; + if(framesCounter % showNumberWaitFrames == 0) + { + framesCounter = 0; + writeNumber = true; + showButton = true; + } + } + else if(!writeMission) + { + framesCounter ++; + if(framesCounter % showMissionWaitFrames == 0) + { + framesCounter = 0; + writeMission = true; + writtingMission = true; + } + } + else if(writeMission && writtingMission) + { + framesCounter++; + if(framesCounter % missionSpeed == 0) + { + framesCounter = 0; + missionLenght++; + + if(missionLenght == missionMaxLength) + { + writtingMission = false; + } + } + } + else if(!writeKeyword) + { + framesCounter++; + if(framesCounter % showKeywordWaitFrames == 0) + { + framesCounter = 0; + writeKeyword = true; + writeEnd = true; + } + } +} +static void EndWritting() +{ + writeEnd = true; + writeKeyword = true; + writeNumber = true; + missionLenght = missionMaxLength; +} +static void BlinkKeyword() +{ + framesCounter++; + if(framesCounter % blinkFrames == 0) + { + framesCounter = 0; + blinkKeyWord = !blinkKeyWord; + } +} diff --git a/games/transmission/screens/screen_title.c b/games/transmission/screens/screen_title.c new file mode 100644 index 00000000..a5ad0a84 --- /dev/null +++ b/games/transmission/screens/screen_title.c @@ -0,0 +1,168 @@ +/********************************************************************************************** +* +* raylib - transmission mission +* +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#include "raylib.h" +#include "screens.h" + +#include <string.h> + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Title screen global variables +static int framesCounter; +static int finishScreen; + +static Texture2D texBackground; +static SpriteFont fontTitle; +static Sound fxTyping; + +static float titleSize; +static Vector2 transmissionPosition; +static Vector2 missionPositon; + +static const char textTitle[20] = "transmissionmission"; + +static Color titleColor; +static int speedText; + +static int transmissionLenght; +static int missionLenght; +static int transmissionMaxLenght; +static int missionMaxLenght; + +static bool writeTransmission; +static bool writeMission; +static bool writeEnd; + +//---------------------------------------------------------------------------------- +// Title Screen Functions Definition +//---------------------------------------------------------------------------------- +static void MissionScreen(); + +// Title Screen Initialization logic +void InitTitleScreen(void) +{ + // TODO: Initialize TITLE screen variables here! + framesCounter = 0; + finishScreen = 0; + + texBackground = LoadTexture("resources/textures/title_background.png"); + fxTyping = LoadSound("resources/audio/fx_typing.ogg"); + fontTitle = LoadSpriteFontEx("resources/fonts/mom_typewritter.ttf", 96, 0, 0); + + titleSize = 44; + transmissionPosition = (Vector2){519, 221}; + missionPositon = (Vector2){580, 261}; + + titleColor = BLACK; + speedText = 15; + + missionLenght = 0; + transmissionLenght = 0; + + missionMaxLenght = 7; + transmissionMaxLenght = 12; + + writeTransmission = true; + writeMission = false; + writeEnd = false; + + currentMission = 0; +} + +// Title Screen Update logic +void UpdateTitleScreen(void) +{ + if (!writeEnd) + { + framesCounter ++; + + if (framesCounter%speedText == 0) + { + framesCounter = 0; + if (writeTransmission) + { + transmissionLenght++; + if (transmissionLenght == transmissionMaxLenght) + { + writeTransmission = false; + writeMission = true; + } + } + else if (writeMission) + { + missionLenght++; + if (missionLenght == missionMaxLenght) + { + writeMission = false; + writeEnd = true; + } + } + + PlaySound(fxTyping); + } + } + + if(IsButtonPressed()) + { + MissionScreen(); + } + else if (IsKeyPressed(KEY_ENTER)) MissionScreen(); +} + +// Title Screen Draw logic +void DrawTitleScreen(void) +{ + DrawTexture(texBackground, 0,0, WHITE); + DrawTextEx(fontTitle, SubText(textTitle, 0, transmissionLenght), transmissionPosition, titleSize, 0, titleColor); + DrawTextEx(fontTitle, SubText(textTitle, 12, missionLenght), missionPositon, titleSize, 0, titleColor); + + DrawButton("start"); +} + +// Title Screen Unload logic +void UnloadTitleScreen(void) +{ + UnloadTexture(texBackground); + UnloadSound(fxTyping); + UnloadSpriteFont(fontTitle); +} + +// Title Screen should finish? +int FinishTitleScreen(void) +{ + return finishScreen; +} + +static void MissionScreen() +{ + transmissionLenght = transmissionMaxLenght; + missionLenght = missionMaxLenght; + writeEnd = true; + //finishScreen = 1; // OPTIONS + finishScreen = true; // GAMEPLAY + //PlaySound(fxCoin); +}
\ No newline at end of file diff --git a/games/transmission/screens/screens.h b/games/transmission/screens/screens.h new file mode 100644 index 00000000..27560d8b --- /dev/null +++ b/games/transmission/screens/screens.h @@ -0,0 +1,143 @@ +/********************************************************************************************** +* +* raylib - transmission mission +* +* Screens Functions Declarations (Init, Update, Draw, Unload) +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +* 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. +* +**********************************************************************************************/ + +#ifndef SCREENS_H +#define SCREENS_H + +#define MAX_CODING_WORDS 12 +#define MAX_MISSION_WORDS 8 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO = 0, TITLE, MISSION, GAMEPLAY, ENDING } GameScreen; + +// Words to be coded or coding words +typedef struct Word { + int id; + Rectangle rec; + Rectangle iniRec; + bool hover; + bool picked; + char text[32]; // text +} Word; + +// Mission information +typedef struct Mission { + int id; + char brief[512]; // Mission briefing + char key[32]; // Mission keyword + char msg[256]; // Message to be coded + int wordsCount; // Number of words to coded + int sols[10]; // Solution code, depends on wordsCount +} Mission; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +GameScreen currentScreen; + +Music music; +Sound fxButton; + +//Mission *missions; + +// UI BUTTON +Rectangle recButton; +float fadeButton; +Color colorButton; +Texture2D texButton; +Vector2 textPositionButton; +int fontSizeButton; +Color textColorButton; + +int currentMission; +int totalMissions; + +SpriteFont fontMission; + +Word messageWords[MAX_MISSION_WORDS]; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Transmission Functions Declaration +//---------------------------------------------------------------------------------- +bool IsButtonPressed(); +void DrawButton(const char *text); +Mission *LoadMissions(const char *fileName); + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLogoScreen(void); +void UpdateLogoScreen(void); +void DrawLogoScreen(void); +void UnloadLogoScreen(void); +int FinishLogoScreen(void); + +//---------------------------------------------------------------------------------- +// Title Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitTitleScreen(void); +void UpdateTitleScreen(void); +void DrawTitleScreen(void); +void UnloadTitleScreen(void); +int FinishTitleScreen(void); + +//---------------------------------------------------------------------------------- +// Mission Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitMissionScreen(void); +void UpdateMissionScreen(void); +void DrawMissionScreen(void); +void UnloadMissionScreen(void); +int FinishMissionScreen(void); + +//---------------------------------------------------------------------------------- +// Gameplay Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitGameplayScreen(void); +void UpdateGameplayScreen(void); +void DrawGameplayScreen(void); +void UnloadGameplayScreen(void); +int FinishGameplayScreen(void); + +//---------------------------------------------------------------------------------- +// Ending Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitEndingScreen(void); +void UpdateEndingScreen(void); +void DrawEndingScreen(void); +void UnloadEndingScreen(void); +int FinishEndingScreen(void); + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H
\ No newline at end of file diff --git a/games/transmission/transmission.c b/games/transmission/transmission.c new file mode 100644 index 00000000..37824a7b --- /dev/null +++ b/games/transmission/transmission.c @@ -0,0 +1,455 @@ +/******************************************************************************************* +* +* raylib - transmission mission +* +* Code and transmit the right message +* +* This game has been created using raylib (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "screens/screens.h" // NOTE: Defines global variable: currentScreen + +#include <stdlib.h> +#include <stdio.h> + +#if defined(PLATFORM_WEB) + #include <emscripten/emscripten.h> +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- +const int screenWidth = 1280; +const int screenHeight = 720; + +// Required variables to manage screen transitions (fade-in, fade-out) +static float transAlpha = 0.0f; +static bool onTransition = false; +static bool transFadeOut = false; +static int transFromScreen = -1; +static int transToScreen = -1; + +// NOTE: Some global variables that require to be visible for all screens, +// are defined in screens.h (i.e. currentScreen) + +//---------------------------------------------------------------------------------- +// Local Functions Declaration +//---------------------------------------------------------------------------------- +static void ChangeToScreen(int screen); // No transition effect + +static void TransitionToScreen(int screen); +static void UpdateTransition(void); +static void DrawTransition(void); + +static void UpdateDrawFrame(void); // Update and Draw one frame + +//---------------------------------------------------------------------------------- +// Main entry point +//---------------------------------------------------------------------------------- +int main(void) +{ + // Initialization + //--------------------------------------------------------- +#ifndef PLATFORM_ANDROID + SetConfigFlags(FLAG_SHOW_LOGO); // | FLAG_FULLSCREEN_MODE); +#endif + // Note windowTitle is unused on Android + InitWindow(screenWidth, screenHeight, "raylib game - transmission mission"); + + // Global data loading (assets that must be available in all screens, i.e. fonts) + InitAudioDevice(); + + music = LoadMusicStream("resources/audio/music_title.ogg"); + fxButton = LoadSound("resources/audio/fx_newspaper.ogg"); + + SetMusicVolume(music, 1.0f); + PlayMusicStream(music); + + fontMission = LoadSpriteFontEx("resources/fonts/traveling_typewriter.ttf", 64, 250, 0); + texButton = LoadTexture("resources/textures/title_ribbon.png"); + + // UI BUTTON + recButton.width = texButton.width; + recButton.height = texButton.height; + recButton.x = screenWidth - recButton.width; + recButton.y = screenHeight - recButton.height - 50; + fadeButton = 0.8f; + colorButton = RED; + textPositionButton = (Vector2){recButton.x + recButton.width/2, recButton.y + recButton.height/2}; + fontSizeButton = 30; + textColorButton = WHITE; + + currentMission = 0; + totalMissions = 4; + + // Setup and Init first screen + currentScreen = LOGO; + InitLogoScreen(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload current screen data before closing + switch (currentScreen) + { + case LOGO: UnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case MISSION: UnloadMissionScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + case ENDING: UnloadEndingScreen(); break; + default: break; + } + + // Unload all global loaded data (i.e. fonts) here! + UnloadMusicStream(music); + UnloadSound(fxButton); + + UnloadSpriteFont(fontMission); + UnloadTexture(texButton); + + CloseAudioDevice(); // Close audio context + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +// Change to next screen, no transition +static void ChangeToScreen(int screen) +{ + // Unload current screen + switch (currentScreen) + { + case LOGO: UnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case MISSION: UnloadMissionScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + case ENDING: UnloadEndingScreen(); break; + default: break; + } + + // Init next screen + switch (screen) + { + case LOGO: InitLogoScreen(); break; + case TITLE: InitTitleScreen(); break; + case MISSION: InitMissionScreen(); break; + case GAMEPLAY: InitGameplayScreen(); break; + case ENDING: InitEndingScreen(); break; + default: break; + } + + currentScreen = screen; +} + +// Define transition to next screen +static void TransitionToScreen(int screen) +{ + onTransition = true; + transFadeOut = false; + transFromScreen = currentScreen; + transToScreen = screen; + transAlpha = 0.0f; +} + +// Update transition effect +static void UpdateTransition(void) +{ + if (!transFadeOut) + { + transAlpha += 0.02f; + + // NOTE: Due to float internal representation, condition jumps on 1.0f instead of 1.05f + // For that reason we compare against 1.01f, to avoid last frame loading stop + if (transAlpha > 1.01f) + { + transAlpha = 1.0f; + + // Unload current screen + switch (transFromScreen) + { + case LOGO: UnloadLogoScreen(); break; + case TITLE: UnloadTitleScreen(); break; + case MISSION: UnloadMissionScreen(); break; + case GAMEPLAY: UnloadGameplayScreen(); break; + case ENDING: UnloadEndingScreen(); break; + default: break; + } + + // Load next screen + switch (transToScreen) + { + case LOGO: InitLogoScreen(); break; + case TITLE: InitTitleScreen(); break; + case MISSION: InitMissionScreen(); break; + case GAMEPLAY: InitGameplayScreen(); break; + case ENDING: InitEndingScreen(); break; + default: break; + } + + currentScreen = transToScreen; + + // Activate fade out effect to next loaded screen + transFadeOut = true; + } + } + else // Transition fade out logic + { + transAlpha -= 0.02f; + + if (transAlpha < -0.01f) + { + transAlpha = 0.0f; + transFadeOut = false; + onTransition = false; + transFromScreen = -1; + transToScreen = -1; + } + } +} + +// Draw transition effect (full-screen rectangle) +static void DrawTransition(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha)); +} + +// Update and draw game frame +static void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + UpdateMusicStream(music); // NOTE: Music keeps playing between screens + + if (!onTransition) + { + switch(currentScreen) + { + case LOGO: + { + UpdateLogoScreen(); + + if (FinishLogoScreen()) TransitionToScreen(TITLE); + + } break; + case TITLE: + { + UpdateTitleScreen(); + + if (FinishTitleScreen()) + { + StopMusicStream(music); + TransitionToScreen(MISSION); + } + + } break; + case MISSION: + { + UpdateMissionScreen(); + + if (FinishMissionScreen()) + { + StopMusicStream(music); + TransitionToScreen(GAMEPLAY); + } + + } break; + case GAMEPLAY: + { + UpdateGameplayScreen(); + + if (FinishGameplayScreen() == 1) TransitionToScreen(ENDING); + //else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE); + + } break; + case ENDING: + { + UpdateEndingScreen(); + + if (FinishEndingScreen() == 1) // Continue to next mission + { + TransitionToScreen(MISSION); + } + else if (FinishEndingScreen() == 2) // Replay current mission + { + PlayMusicStream(music); + TransitionToScreen(TITLE); + } + + } break; + default: break; + } + } + else UpdateTransition(); // Update transition (fade-in, fade-out) + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + switch(currentScreen) + { + case LOGO: DrawLogoScreen(); break; + case TITLE: DrawTitleScreen(); break; + case MISSION: DrawMissionScreen(); break; + case GAMEPLAY: DrawGameplayScreen(); break; + case ENDING: DrawEndingScreen(); break; + default: break; + } + + // Draw full screen rectangle in front of everything + if (onTransition) DrawTransition(); + + //DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} + +// Load missions from text file +Mission *LoadMissions(const char *fileName) +{ + Mission *missions = NULL; + char buffer[512]; + + int missionsCount = 0; + + FILE *misFile = fopen(fileName, "rt"); + + if (misFile == NULL) printf("[%s] Missions file could not be opened\n", fileName); + else + { + // First pass to get total missions count + while (!feof(misFile)) + { + fgets(buffer, 512, misFile); + + switch (buffer[0]) + { + case 't': sscanf(buffer, "t %i", &missionsCount); break; + default: break; + } + } + + if (missionsCount > 0) missions = (Mission *)malloc(missionsCount*sizeof(Mission)); + else return NULL; + + rewind(misFile); // Return to the beginning of the file, to read again + + int missionNum = 0; + + while (!feof(misFile)) + { + fgets(buffer, 512, misFile); + + if (missionNum < missionsCount) + { + switch (buffer[0]) + { + case 'b': + { + // New mission brief starts! + missions[missionNum].id = missionNum; + sscanf(buffer, "b %[^\n]s", missions[missionNum].brief); + } break; + case 'k': sscanf(buffer, "k %[^\n]s", missions[missionNum].key); break; + case 'm': + { + // NOTE: Message is loaded as is, needs to be processed! + sscanf(buffer, "m %[^\n]s", missions[missionNum].msg); + } break; + case 's': + { + sscanf(buffer, "s %i %i %i %i %i %i %i %i", + &missions[missionNum].sols[0], + &missions[missionNum].sols[1], + &missions[missionNum].sols[2], + &missions[missionNum].sols[3], + &missions[missionNum].sols[4], + &missions[missionNum].sols[5], + &missions[missionNum].sols[6], + &missions[missionNum].sols[7]); + + missions[missionNum].wordsCount = 0; + + for (int i = 0; i < 8; i++) + { + if (missions[missionNum].sols[i] > -1) + { + missions[missionNum].wordsCount++; + } + } + + TraceLog(LOG_WARNING, "Mission %i - Words count %i", missionNum, missions[missionNum].wordsCount); + + missionNum++; + } break; + default: break; + } + } + } + + if (missionsCount != missionNum) TraceLog(LOG_WARNING, "Missions count and loaded missions don't match!"); + } + + fclose(misFile); + + if (missions != NULL) + { + TraceLog(LOG_INFO, "Missions loaded: %i", missionsCount); + TraceLog(LOG_INFO, "Missions loaded successfully!"); + } + + return missions; +} + +bool IsButtonPressed() +{ + if (CheckCollisionPointRec(GetMousePosition(), recButton)) + { + fadeButton = 1.0f; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsGestureDetected(GESTURE_TAP)) + { + PlaySound(fxButton); + return true; + } + } + else fadeButton = 0.80f; + + return false; +} + +void DrawButton(const char *text) +{ + //DrawRectangleRec(recButton, Fade(colorButton, fadeButton)); + DrawTexturePro(texButton, (Rectangle){0,0,texButton.width, texButton.height}, recButton, (Vector2){0,0},0, Fade(WHITE, fadeButton)); + Vector2 measure = MeasureTextEx(fontMission, text, fontSizeButton, 0); + Vector2 textPos = {textPositionButton.x - measure.x/2 + 10, textPositionButton.y - measure.y/2 - 10}; + DrawTextEx(fontMission, text, textPos , fontSizeButton, 0, textColorButton); +} |
