mirror of
https://github.com/sigonasr2/hamster.git
synced 2025-04-16 05:49:17 -05:00
Initial commit
This commit is contained in:
commit
278edfcb2b
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: Moros1138
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. Arch, Manjaro, Ubuntu, Windows]
|
||||||
|
- Toolchain: [e.g. Clang, GCC, Visual Studio]
|
||||||
|
- Toolchain Version: [e.g. gcc 11.2.0]
|
||||||
|
- CMake Version: [e.g. 3.10]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[Feature Request]"
|
||||||
|
labels: enhancement
|
||||||
|
assignees: Moros1138
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
build
|
||||||
|
linux-build
|
||||||
|
emscripten-build
|
||||||
|
nmake-build
|
||||||
|
mingw-build
|
||||||
|
vs-build
|
||||||
|
.vscode
|
||||||
|
.cache
|
292
CMakeLists.txt
Normal file
292
CMakeLists.txt
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
# require version 3.10 or higher
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Project
|
||||||
|
#
|
||||||
|
# - dictates the output executable filename
|
||||||
|
#
|
||||||
|
project(TestApp)
|
||||||
|
|
||||||
|
# Options you can set via command-line
|
||||||
|
option(HAS_TERMINAL "Show a terminal window for STDOUT/STDERR" ON)
|
||||||
|
|
||||||
|
#
|
||||||
|
# C_CXX_SOURCES_DIR
|
||||||
|
#
|
||||||
|
# - the place where your C/C++ source files are located
|
||||||
|
#
|
||||||
|
set(C_CXX_SOURCES_DIR "src")
|
||||||
|
|
||||||
|
#
|
||||||
|
# C_CXX_HEADERS_DIR
|
||||||
|
#
|
||||||
|
# - the place where your C/C++ header files are located
|
||||||
|
#
|
||||||
|
set(C_CXX_HEADERS_DIR "include")
|
||||||
|
|
||||||
|
#
|
||||||
|
# ASSETS_DIR
|
||||||
|
#
|
||||||
|
# - the place where your pictures, sound files, etc.. live
|
||||||
|
#
|
||||||
|
set(ASSETS_DIR "assets")
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING!! #
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
# Set C++ Standards
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
# output executable basename
|
||||||
|
set(OutputExecutable "${CMAKE_PROJECT_NAME}")
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Directories
|
||||||
|
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
|
||||||
|
# We need to specify the output for each configuration to make it work
|
||||||
|
# on Visual Studio solutions.
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/lib")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_PROFILE "${CMAKE_BINARY_DIR}/bin")
|
||||||
|
|
||||||
|
set(SOURCE_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${ASSETS_DIR})
|
||||||
|
set(SOURCE_CXX_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${C_CXX_HEADERS_DIR})
|
||||||
|
set(SOURCE_CXX_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${C_CXX_SOURCES_DIR})
|
||||||
|
|
||||||
|
# Source Files are Curated Here
|
||||||
|
file(
|
||||||
|
GLOB_RECURSE SOURCE_CXX_FILES
|
||||||
|
"${SOURCE_CXX_SRC_DIR}/*.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Search in the "cmake" directory for additional CMake modules.
|
||||||
|
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
# Executable aka binary output
|
||||||
|
add_executable(${OutputExecutable} ${SOURCE_CXX_FILES})
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# MacOS
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
|
||||||
|
# OpenGL
|
||||||
|
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${OpenGL_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${OutputExecutable} ${OpenGL_LIBRARIES} OpenGL::GL)
|
||||||
|
|
||||||
|
# Carbon
|
||||||
|
FIND_LIBRARY(CARBON_LIBRARY Carbon)
|
||||||
|
target_link_libraries(${OutputExecutable} ${CARBON_LIBRARY})
|
||||||
|
|
||||||
|
# GLUT
|
||||||
|
find_package(GLUT REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} ${GLUT_LIBRARIES})
|
||||||
|
|
||||||
|
# Threads
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} Threads::Threads)
|
||||||
|
include_directories(${Threads_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
find_package(PNG REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} PNG::PNG)
|
||||||
|
include_directories(${PNG_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
endif() # APPLE
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Windows: MinGW
|
||||||
|
######################################################################
|
||||||
|
if(WIN32 AND MINGW)
|
||||||
|
|
||||||
|
# OpenGL
|
||||||
|
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${OpenGL_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${OutputExecutable} ${OpenGL_LIBRARIES} OpenGL::GL)
|
||||||
|
|
||||||
|
if (NOT HAS_TERMINAL)
|
||||||
|
target_link_libraries(${OutputExecutable} -mwindows -municode)
|
||||||
|
endif (NOT HAS_TERMINAL)
|
||||||
|
|
||||||
|
# GDI+
|
||||||
|
set(GDIPLUS_LIBRARY gdiplus)
|
||||||
|
target_link_libraries(${OutputExecutable} ${GDIPLUS_LIBRARY})
|
||||||
|
|
||||||
|
# Shlwapi
|
||||||
|
set(SHLWAPI_LIBRARY shlwapi)
|
||||||
|
target_link_libraries(${OutputExecutable} ${SHLWAPI_LIBRARY})
|
||||||
|
|
||||||
|
# Dwmapi
|
||||||
|
set(DWMAPI_LIBRARY dwmapi)
|
||||||
|
target_link_libraries(${OutputExecutable} ${DWMAPI_LIBRARY})
|
||||||
|
|
||||||
|
# stdc++fs
|
||||||
|
target_link_libraries(${OutputExecutable} stdc++fs)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Windows: Visual Studio / MSVC
|
||||||
|
######################################################################
|
||||||
|
if(WIN32 AND MSVC)
|
||||||
|
|
||||||
|
# OpenGL
|
||||||
|
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${OpenGL_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${OutputExecutable} ${OpenGL_LIBRARIES} OpenGL::GL)
|
||||||
|
|
||||||
|
# set the startup project to the target executable instead of ALL_BUILD
|
||||||
|
set_property(
|
||||||
|
DIRECTORY
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
PROPERTY
|
||||||
|
VS_STARTUP_PROJECT
|
||||||
|
${OutputExecutable}
|
||||||
|
)
|
||||||
|
|
||||||
|
# set working directory for Visual Studio Debugger
|
||||||
|
set_target_properties(
|
||||||
|
${OutputExecutable} PROPERTIES
|
||||||
|
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
# set subsytem, console if HAS_TERMINAL is true. windows if not
|
||||||
|
if (HAS_TERMINAL)
|
||||||
|
target_link_options(${OutputExecutable} PRIVATE "/SUBSYSTEM:CONSOLE")
|
||||||
|
else ()
|
||||||
|
target_link_options(${OutputExecutable} PRIVATE "/SUBSYSTEM:WINDOWS")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# GDI+
|
||||||
|
set(GDIPLUS_LIBRARY gdiplus)
|
||||||
|
target_link_libraries(${OutputExecutable} ${GDIPLUS_LIBRARY})
|
||||||
|
|
||||||
|
# Shlwapi
|
||||||
|
set(SHLWAPI_LIBRARY shlwapi)
|
||||||
|
target_link_libraries(${OutputExecutable} ${SHLWAPI_LIBRARY})
|
||||||
|
|
||||||
|
# Dwmapi
|
||||||
|
set(DWMAPI_LIBRARY dwmapi)
|
||||||
|
target_link_libraries(${OutputExecutable} ${DWMAPI_LIBRARY})
|
||||||
|
|
||||||
|
endif() # Visual Studio / MSVC
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Linux: using anything?
|
||||||
|
######################################################################
|
||||||
|
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN)
|
||||||
|
|
||||||
|
# OpenGL
|
||||||
|
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
include_directories(${OpenGL_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${OutputExecutable} ${OpenGL_LIBRARIES} OpenGL::GL)
|
||||||
|
|
||||||
|
# X11
|
||||||
|
find_package(X11 REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} X11::X11)
|
||||||
|
|
||||||
|
include_directories(${X11_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# Threads
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} Threads::Threads)
|
||||||
|
include_directories(${Threads_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
find_package(PNG REQUIRED)
|
||||||
|
target_link_libraries(${OutputExecutable} PNG::PNG)
|
||||||
|
include_directories(${PNG_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# stdc++fs
|
||||||
|
target_link_libraries(${OutputExecutable} stdc++fs)
|
||||||
|
|
||||||
|
# dl, for miniaudio
|
||||||
|
target_link_libraries(${OutputExecutable} dl)
|
||||||
|
|
||||||
|
endif() # Linux
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Emscripten
|
||||||
|
######################################################################
|
||||||
|
if (EMSCRIPTEN)
|
||||||
|
|
||||||
|
# Generate an HTML file
|
||||||
|
set(CMAKE_EXECUTABLE_SUFFIX .html)
|
||||||
|
|
||||||
|
# Build Cache: SDL2_mixer, libpng, zlib
|
||||||
|
execute_process(COMMAND "${EMSCRIPTEN_ROOT_PATH}/embuilder${EMCC_SUFFIX}" build sdl2_mixer libpng zlib)
|
||||||
|
|
||||||
|
if(EXISTS "${SOURCE_DATA_DIR}" AND IS_DIRECTORY "${SOURCE_DATA_DIR}")
|
||||||
|
target_link_options(
|
||||||
|
${OutputExecutable}
|
||||||
|
PRIVATE
|
||||||
|
-sALLOW_MEMORY_GROWTH=1
|
||||||
|
-sMAX_WEBGL_VERSION=2
|
||||||
|
-sMIN_WEBGL_VERSION=2
|
||||||
|
-sUSE_LIBPNG=1
|
||||||
|
-sLLD_REPORT_UNDEFINED
|
||||||
|
--preload-file ${SOURCE_DATA_DIR}@assets)
|
||||||
|
else()
|
||||||
|
target_link_options(
|
||||||
|
${OutputExecutable}
|
||||||
|
PRIVATE
|
||||||
|
-sALLOW_MEMORY_GROWTH=1
|
||||||
|
-sMAX_WEBGL_VERSION=2
|
||||||
|
-sMIN_WEBGL_VERSION=2
|
||||||
|
-sUSE_LIBPNG=1
|
||||||
|
-sLLD_REPORT_UNDEFINED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif() # Emscripten
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Set include directory
|
||||||
|
######################################################################
|
||||||
|
if(IS_DIRECTORY ${SOURCE_CXX_INCLUDE_DIR})
|
||||||
|
include_directories(${SOURCE_CXX_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Copy assets/ directory target
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
set(DATA_OUTPUT_DIR ${CMAKE_BINARY_DIR}/bin/${ASSETS_DIR})
|
||||||
|
|
||||||
|
file(GLOB_RECURSE src_data_files
|
||||||
|
RELATIVE ${SOURCE_DATA_DIR}/ "${SOURCE_DATA_DIR}/*.*" "${SOURCE_DATA_DIR}/*")
|
||||||
|
foreach(fn ${src_data_files})
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${DATA_OUTPUT_DIR}/${fn}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_DATA_DIR}/${fn} ${DATA_OUTPUT_DIR}/${fn}
|
||||||
|
MAIN_DEPENDENCY ${SOURCE_DATA_DIR}/${fn})
|
||||||
|
list(APPEND out_data_files ${DATA_OUTPUT_DIR}/${fn})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
add_custom_target(copy_data DEPENDS ${out_data_files})
|
||||||
|
|
||||||
|
# Copy Asset Files, if not Emscripten
|
||||||
|
if (NOT EMSCRIPTEN)
|
||||||
|
add_dependencies(${OutputExecutable} copy_data)
|
||||||
|
endif()
|
69
LICENSE
Normal file
69
LICENSE
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
The following license applies to the repository, unless otherwised credit.
|
||||||
|
|
||||||
|
+----------------------------------------------------------------------------
|
||||||
|
| The Unlicense
|
||||||
|
+----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||||
|
this software, either in source code form or as a compiled binary, for any
|
||||||
|
purpose, commercial or non-commercial, and by any means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors of
|
||||||
|
this software dedicate any and all copyright interest in the software to
|
||||||
|
the public domain. We make this dedication for the benefit of the public
|
||||||
|
at large and to the detriment of our heirs and successors. We intend this
|
||||||
|
dedication to be an overt act of relinquishment in perpetuity of all present
|
||||||
|
and future rights to this software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to the project's repository:
|
||||||
|
|
||||||
|
https://github.com/Moros1138/pge-template-project or moros1138@gmail.com
|
||||||
|
|
||||||
|
|
||||||
|
+----------------------------------------------------------------------------
|
||||||
|
| External Licenses
|
||||||
|
+----------------------------------------------------------------------------
|
||||||
|
The following license applies to usage of the olcPixelGameEngine and olcSoundWaveEngine:
|
||||||
|
|
||||||
|
https://github.com/OneLoneCoder/olcPixelGameEngine
|
||||||
|
https://github.com/OneLoneCoder/olcSoundWaveEngine
|
||||||
|
|
||||||
|
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2018 - 2022 OneLoneCoder.com
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
217
README.md
Normal file
217
README.md
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
# PGE Template Project v2.25
|
||||||
|
|
||||||
|
This is a template project for use with the [olcPixelGameEngine](https://github.com/OneLoneCoder/olcPixelGameEngine). It serves as a jumping off point for you to build your masterpiece application.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
CMake script for cross-platform building. Tested environments include:
|
||||||
|
|
||||||
|
* Linux - with UNIX Makefiles, GNU GCC and LLVM Clang
|
||||||
|
* MacOS - with UNIX Makefiles, XCode and LLVM Clang
|
||||||
|
* Windows - with Visual Studio, NMake Makefiles, and MinGW Makefiles
|
||||||
|
* Emscripten - with UNIX Makefiles, NMake Makefiles, and MinGW Makefiles
|
||||||
|
|
||||||
|
# Preparing your Environment
|
||||||
|
|
||||||
|
The instructions to prepare your environment have been broken up for convenience. Simply follow the instructions that are pertinent to your situation.
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
|
||||||
|
### **Requirements**
|
||||||
|
|
||||||
|
* C/C++ Toolchain for your Linux distro
|
||||||
|
* CMake
|
||||||
|
* Git
|
||||||
|
* libpng
|
||||||
|
* Mesa OpenGL Development Libraries
|
||||||
|
|
||||||
|
### **Ubuntu and Ubuntu based distros**
|
||||||
|
|
||||||
|
Update your package manager by issuing the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
|
Install toolchain and required software by issuing the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install build-essential cmake git libpng-dev libglu1-mesa-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Arch, Manjaro, and Arch based distros**
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo pacman -Sy base-devel cmake git libpng mesa
|
||||||
|
```
|
||||||
|
|
||||||
|
## MacOS
|
||||||
|
|
||||||
|
### **Requirements**
|
||||||
|
|
||||||
|
* XCode
|
||||||
|
* [Homebrew Package Manager](https://brew.sh/)
|
||||||
|
* libpng
|
||||||
|
* CMake
|
||||||
|
* git
|
||||||
|
|
||||||
|
Install XCode from the App Store.
|
||||||
|
|
||||||
|
Open the ``Terminal`` App from Finder. go to Applications -> Utilities
|
||||||
|
|
||||||
|
Follow the instructions at the [Homebrew Website](https://brew.sh/) to install the Homebrew package manager.
|
||||||
|
|
||||||
|
Once Homebrew is installed, issue the following command to install ``cmake``,``libpng``, and ``git``:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
brew install libpng
|
||||||
|
brew install cmake
|
||||||
|
brew install git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
* Chocolatey
|
||||||
|
* CMake
|
||||||
|
* Toolchain (MinGW or Visual Studio / NMake)
|
||||||
|
|
||||||
|
The following will be required whether you use MinGW or Visual Studio.You will need to open Powershell, as Administrator.
|
||||||
|
|
||||||
|
Visit the [Chocolatey website](https://chocolatey.org/) for instructions on how to install Chocolatey.
|
||||||
|
|
||||||
|
Once you've got Chocolatey installed, we can install CMake:
|
||||||
|
|
||||||
|
```
|
||||||
|
choco install cmake
|
||||||
|
```
|
||||||
|
|
||||||
|
Say ``yes`` to all of the scripts Chocolatey wants you to run!
|
||||||
|
|
||||||
|
After the installation has completed, find the Cmake ``bin`` directory, it is typically ``C:\Program Files\CMake\bin`` and add it to your path!
|
||||||
|
|
||||||
|
Confirm CMake is installed and in your path by issuing the following command in a Command Prompt:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --version
|
||||||
|
```
|
||||||
|
|
||||||
|
If you recieve an ``command not found`` error double check that you have actually added CMake to your path.
|
||||||
|
|
||||||
|
## MinGW
|
||||||
|
|
||||||
|
Install MinGW via ``choco install mingw`` from Powershell as Administrator
|
||||||
|
|
||||||
|
|
||||||
|
## Visual Studio / NMake
|
||||||
|
|
||||||
|
Download and install [Visual Studio: Community Edition](https://visualstudio.microsoft.com/downloads/).
|
||||||
|
|
||||||
|
Ensure that you have installed the Desktop C++ option!
|
||||||
|
|
||||||
|
# **Usage**
|
||||||
|
|
||||||
|
IF YOU HAVE MADE IT HERE AND YOU HAVE NOT SET UP YOUR DEVELOPMENT ENVIRONMENT, GO BACK UP AND READ THE INSTRUCTIONS AGAIN!
|
||||||
|
|
||||||
|
## Linux / MacOS (with default toolchains)
|
||||||
|
|
||||||
|
Open a Terminal and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B linux-build -G "Unix Makefiles"
|
||||||
|
```
|
||||||
|
|
||||||
|
CMake will generate UNIX Makefiles you can use to build the project, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --build linux-build
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiled binary will be located in ``linux-build/bin`` directory.
|
||||||
|
|
||||||
|
**NOTE: if you're executing the program, ensure you have the correct working directory, which contains the executable!**
|
||||||
|
|
||||||
|
## MacOS (with XCode)
|
||||||
|
|
||||||
|
Open a Terminal and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B xcode-build -G "xcode"
|
||||||
|
```
|
||||||
|
|
||||||
|
CMake will generate an XCode project in ``xcode-build``. You can use it like any other XCode project.
|
||||||
|
|
||||||
|
## Linux / MacOS (Emscripten)
|
||||||
|
|
||||||
|
**These instructions assume you have Emscripten installed, activated, and have the environment set up for an active Terminal.**
|
||||||
|
|
||||||
|
Open a Terminal and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
emcmake cmake . -B emscripten-build
|
||||||
|
```
|
||||||
|
|
||||||
|
Emscripten's ``emcmake`` utility will invoke CMake with all the magic required to make it work with Emscripten. Generating UNIX Makefiles you can use to build the project, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --build emscripten-build
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiled HTML, Javascript, WebAssembly, and Data will be in the ``emscripten-build/bin`` directory.
|
||||||
|
|
||||||
|
If you lack some sort of live server extension to your IDE, you can view it using the ``emrun`` utility, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
emrun path/to/build/bin/PROJECTNAME.html
|
||||||
|
```
|
||||||
|
|
||||||
|
This command should launch the project in your default web browser.
|
||||||
|
|
||||||
|
## Windows (MinGW)
|
||||||
|
|
||||||
|
Open the ``Command Prompt`` prompt and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B mingw-build -G "MinGW Makefiles"
|
||||||
|
```
|
||||||
|
|
||||||
|
CMake will generate MinGW Makefiles you can use to build the project, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --build mingw-build
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiled binary will be located in the ``mingw-build/bin`` directory.
|
||||||
|
|
||||||
|
**NOTE: if you're executing the program, ensure you have the correct working directory, which contains the executable!**
|
||||||
|
|
||||||
|
## Windows (NMake)
|
||||||
|
|
||||||
|
Open the ``x64 Native Tools Command Prompt for VS 2022`` prompt and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B nmake-build -G "NMake Makefiles"
|
||||||
|
```
|
||||||
|
|
||||||
|
CMake will generate NMake Makefiles you can use to build the project, like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake --build nmake-build
|
||||||
|
```
|
||||||
|
|
||||||
|
The compiled binary will be located in ``nmake-build/bin`` directory.
|
||||||
|
|
||||||
|
**NOTE: if you're executing the program, ensure you have the correct working directory, which contains the executable!**
|
||||||
|
|
||||||
|
## Windows (Visual Studio)
|
||||||
|
|
||||||
|
Open the ``Command Prompt`` prompt and navigate to the directory which you downloaded the project. Issue the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake . -B vs-build
|
||||||
|
```
|
||||||
|
|
||||||
|
CMake will generate a Visual Studio solution and project in ``vs-build``. You can use it like any other Visual Studio Project.
|
||||||
|
|
0
assets/.keepme
Normal file
0
assets/.keepme
Normal file
BIN
assets/gfx/space.png
Normal file
BIN
assets/gfx/space.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
BIN
assets/sounds/Explosions1.wav
Executable file
BIN
assets/sounds/Explosions1.wav
Executable file
Binary file not shown.
BIN
assets/sounds/Laser_Shoot11.wav
Executable file
BIN
assets/sounds/Laser_Shoot11.wav
Executable file
Binary file not shown.
BIN
assets/sounds/bg-music.wav
Executable file
BIN
assets/sounds/bg-music.wav
Executable file
Binary file not shown.
BIN
assets/sounds/lose9.wav
Executable file
BIN
assets/sounds/lose9.wav
Executable file
Binary file not shown.
BIN
assets/sounds/thruster.wav
Normal file
BIN
assets/sounds/thruster.wav
Normal file
Binary file not shown.
92621
include/miniaudio.h
Normal file
92621
include/miniaudio.h
Normal file
File diff suppressed because it is too large
Load Diff
477
include/olcPGEX_MiniAudio.h
Normal file
477
include/olcPGEX_MiniAudio.h
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
olcPGEX_MiniAudio.h
|
||||||
|
|
||||||
|
+-------------------------------------------------------------+
|
||||||
|
| OneLoneCoder Pixel Game Engine Extension |
|
||||||
|
| MiniAudio v1.5 |
|
||||||
|
+-------------------------------------------------------------+
|
||||||
|
|
||||||
|
NOTE: UNDER ACTIVE DEVELOPMENT - THERE MAY BE BUGS/GLITCHES
|
||||||
|
|
||||||
|
What is this?
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
This extension abstracts the very robust and powerful miniaudio
|
||||||
|
library. It provides simple loading and playback of WAV and MP3
|
||||||
|
files. Because it's built on top of miniaudio, it requires next
|
||||||
|
to no addictional build configurations in order to be built
|
||||||
|
for cross-platform.
|
||||||
|
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2023 Moros Smith <moros1138@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
Links
|
||||||
|
~~~~~
|
||||||
|
YouTube: https://www.youtube.com/@Moros1138
|
||||||
|
GitHub: https://www.github.com/Moros1138
|
||||||
|
Homepage: https://www.moros1138.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "olcPixelGameEngine.h"
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#ifdef OLC_PGEX_MINIAUDIO
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "miniaudio.h"
|
||||||
|
|
||||||
|
namespace olc
|
||||||
|
{
|
||||||
|
class MiniAudio : public olc::PGEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name = "olcPGEX_MiniAudio v1.5";
|
||||||
|
|
||||||
|
public:
|
||||||
|
MiniAudio();
|
||||||
|
~MiniAudio();
|
||||||
|
virtual bool OnBeforeUserUpdate(float& fElapsedTime) override;
|
||||||
|
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
|
||||||
|
static bool backgroundPlay;
|
||||||
|
|
||||||
|
public: // CONFIGURATION
|
||||||
|
// set whether audio will continue playing when the app has lost focus
|
||||||
|
void SetBackgroundPlay(bool state);
|
||||||
|
|
||||||
|
public: // LOADING ROUTINES
|
||||||
|
const int LoadSound(const std::string& path);
|
||||||
|
void UnloadSound(const int id);
|
||||||
|
|
||||||
|
public: // PLAYBACK CONTROLS
|
||||||
|
// plays a sample, can be set to loop
|
||||||
|
void Play(const int id, const bool loop = false);
|
||||||
|
// plays a sound file, as a one off, and automatically unloads it
|
||||||
|
void Play(const std::string& path);
|
||||||
|
// stops a sample, rewinds to beginning
|
||||||
|
void Stop(const int id);
|
||||||
|
// pauses a sample, does not change position
|
||||||
|
void Pause(const int id);
|
||||||
|
// toggle between play and pause
|
||||||
|
void Toggle(const int id, bool rewind = false);
|
||||||
|
|
||||||
|
public: // SEEKING CONTROLS
|
||||||
|
// seek to the provided position in the sound, by milliseconds
|
||||||
|
void Seek(const int id, const unsigned long long milliseconds);
|
||||||
|
// seek to the provided position in the sound, by float 0.f is beginning, 1.0f is end
|
||||||
|
void Seek(const int id, const float& location);
|
||||||
|
// seek forward from current position by the provided time
|
||||||
|
void Forward(const int id, const unsigned long long milliseconds);
|
||||||
|
// seek forward from current position by the provided time
|
||||||
|
void Rewind(const int id, const unsigned long long milliseconds);
|
||||||
|
|
||||||
|
public: // MISC CONTROLS
|
||||||
|
// set volume of a sound, 0.0f is mute, 1.0f is full
|
||||||
|
void SetVolume(const int id, const float& volume);
|
||||||
|
// set pan of a sound, -1.0f is left, 1.0f is right, 0.0f is center
|
||||||
|
void SetPan(const int id, const float& pan);
|
||||||
|
// set pitch of a sound, 1.0f is normal
|
||||||
|
void SetPitch(const int id, const float& pitch);
|
||||||
|
|
||||||
|
public: // MISC INFORMATION
|
||||||
|
// determine if a sound is playing
|
||||||
|
bool IsPlaying(const int id);
|
||||||
|
// gets the current position in the sound, in milliseconds
|
||||||
|
unsigned long long GetCursorMilliseconds(const int id);
|
||||||
|
// gets the current position in the sound, as a float between 0.0f and 1.0f
|
||||||
|
float GetCursorFloat(const int id);
|
||||||
|
|
||||||
|
public: // ADVANCED FEATURES for those who want to use more of miniaudio
|
||||||
|
// gets the currently loaded persistent sounds
|
||||||
|
const std::vector<ma_sound*>& GetSounds() const;
|
||||||
|
// gets the currently loaded one-off sounds
|
||||||
|
const std::vector<ma_sound*>& GetOneOffSounds() const;
|
||||||
|
// gets a pointer to the ma_device
|
||||||
|
ma_device* GetDevice();
|
||||||
|
// gets a pointer to the ma_engine
|
||||||
|
ma_engine* GetEngine();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Soooo, i'm not going to spend a whole lot of time
|
||||||
|
documenting miniaudio features, if you want to
|
||||||
|
know more I invite you to visit their very very
|
||||||
|
nicely documented webiste at:
|
||||||
|
|
||||||
|
https://miniaud.io/docs/manual/index.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
ma_device device;
|
||||||
|
ma_engine engine;
|
||||||
|
ma_resource_manager resourceManager;
|
||||||
|
|
||||||
|
// sample rate for the device and engine
|
||||||
|
int sampleRate;
|
||||||
|
// this is where the sounds are kept
|
||||||
|
std::vector<ma_sound*> vecSounds;
|
||||||
|
std::vector<ma_sound*> vecOneOffSounds;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EXCEPTIONS, long story short. I needed to be able
|
||||||
|
* to construct the PGEX in a state where it could
|
||||||
|
* fail at runtime. If you have a better way of
|
||||||
|
* accomplishing the PGEX pattern without using
|
||||||
|
* exceptions, I'm open to suggestions!
|
||||||
|
*/
|
||||||
|
struct MiniAudioDeviceException : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const throw()
|
||||||
|
{
|
||||||
|
return "Failed to initialize a device.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MiniAudioResourceManagerException : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const throw()
|
||||||
|
{
|
||||||
|
return "Failed to initialize the resource manager.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MiniAudioEngineException : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const throw()
|
||||||
|
{
|
||||||
|
return "Failed to initialize the audio engine.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MiniAudioSoundException : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const throw()
|
||||||
|
{
|
||||||
|
return "Failed to initialize a sound.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OLC_PGEX_MINIAUDIO
|
||||||
|
#undef OLC_PGEX_MINIAUDIO
|
||||||
|
|
||||||
|
namespace olc
|
||||||
|
{
|
||||||
|
bool MiniAudio::backgroundPlay = false;
|
||||||
|
|
||||||
|
MiniAudio::MiniAudio() : olc::PGEX(true)
|
||||||
|
{
|
||||||
|
sampleRate = 48000;
|
||||||
|
|
||||||
|
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
|
deviceConfig.playback.format = ma_format_f32;
|
||||||
|
deviceConfig.playback.channels = 2;
|
||||||
|
deviceConfig.sampleRate = sampleRate;
|
||||||
|
deviceConfig.dataCallback = MiniAudio::data_callback;
|
||||||
|
deviceConfig.pUserData = &engine;
|
||||||
|
|
||||||
|
if(ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS)
|
||||||
|
throw MiniAudioDeviceException();
|
||||||
|
|
||||||
|
ma_resource_manager_config resourceManagerConfig = ma_resource_manager_config_init();
|
||||||
|
resourceManagerConfig.decodedFormat = ma_format_f32;
|
||||||
|
resourceManagerConfig.decodedChannels = 0;
|
||||||
|
resourceManagerConfig.decodedSampleRate = sampleRate;
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
resourceManagerConfig.jobThreadCount = 0;
|
||||||
|
resourceManagerConfig.flags |= MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING;
|
||||||
|
resourceManagerConfig.flags |= MA_RESOURCE_MANAGER_FLAG_NO_THREADING;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(ma_resource_manager_init(&resourceManagerConfig, &resourceManager) != MA_SUCCESS)
|
||||||
|
throw MiniAudioResourceManagerException();
|
||||||
|
|
||||||
|
ma_engine_config engineConfig = ma_engine_config_init();
|
||||||
|
engineConfig.pDevice = &device;
|
||||||
|
engineConfig.pResourceManager = &resourceManager;
|
||||||
|
|
||||||
|
if(ma_engine_init(&engineConfig, &engine) != MA_SUCCESS)
|
||||||
|
throw MiniAudioEngineException();
|
||||||
|
|
||||||
|
MiniAudio::backgroundPlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MiniAudio::~MiniAudio()
|
||||||
|
{
|
||||||
|
for(auto sound : vecSounds)
|
||||||
|
{
|
||||||
|
if(sound != nullptr)
|
||||||
|
{
|
||||||
|
ma_sound_uninit(sound);
|
||||||
|
delete sound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_resource_manager_uninit(&resourceManager);
|
||||||
|
|
||||||
|
ma_engine_uninit(&engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MiniAudio::OnBeforeUserUpdate(float& fElapsedTime)
|
||||||
|
{
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
ma_resource_manager_process_next_job(&resourceManager);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i = 0; i < vecOneOffSounds.size(); i++)
|
||||||
|
{
|
||||||
|
if(!ma_sound_is_playing(vecOneOffSounds.at(i)))
|
||||||
|
{
|
||||||
|
ma_sound_uninit(vecOneOffSounds.at(i));
|
||||||
|
vecOneOffSounds.erase(vecOneOffSounds.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||||
|
{
|
||||||
|
if(!MiniAudio::backgroundPlay && !pge->IsFocused())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ma_engine_read_pcm_frames((ma_engine*)(pDevice->pUserData), pOutput, frameCount, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::SetBackgroundPlay(bool state)
|
||||||
|
{
|
||||||
|
MiniAudio::backgroundPlay = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MiniAudio::LoadSound(const std::string& path)
|
||||||
|
{
|
||||||
|
// create the sound
|
||||||
|
ma_sound* sound = new ma_sound();
|
||||||
|
|
||||||
|
// load it from the file and decode it
|
||||||
|
if(ma_sound_init_from_file(&engine, path.c_str(), MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, NULL, NULL, sound) != MA_SUCCESS)
|
||||||
|
throw MiniAudioSoundException();
|
||||||
|
|
||||||
|
// attempt to re-use an empty slot
|
||||||
|
for(int i = 0; i < vecSounds.size(); i++)
|
||||||
|
{
|
||||||
|
if(vecSounds.at(i) == nullptr)
|
||||||
|
{
|
||||||
|
vecSounds.at(i) = sound;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no empty slots, make more room!
|
||||||
|
const int id = vecSounds.size();
|
||||||
|
vecSounds.push_back(sound);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::UnloadSound(const int id)
|
||||||
|
{
|
||||||
|
ma_sound_uninit(vecSounds.at(id));
|
||||||
|
delete vecSounds.at(id);
|
||||||
|
vecSounds.at(id) = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Play(const int id, const bool loop)
|
||||||
|
{
|
||||||
|
if(ma_sound_is_playing(vecSounds.at(id)))
|
||||||
|
{
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_sound_set_looping(vecSounds.at(id), loop);
|
||||||
|
ma_sound_start(vecSounds.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Play(const std::string& path)
|
||||||
|
{
|
||||||
|
// create the sound
|
||||||
|
ma_sound* sound = new ma_sound();
|
||||||
|
|
||||||
|
// load it from the file and decode it
|
||||||
|
if(ma_sound_init_from_file(&engine, path.c_str(), MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, NULL, NULL, sound) != MA_SUCCESS)
|
||||||
|
throw MiniAudioSoundException();
|
||||||
|
|
||||||
|
ma_sound_start(sound);
|
||||||
|
vecOneOffSounds.push_back(sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Stop(const int id)
|
||||||
|
{
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0);
|
||||||
|
ma_sound_stop(vecSounds.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Pause(const int id)
|
||||||
|
{
|
||||||
|
auto it = vecSounds.begin() + id;
|
||||||
|
ma_sound_stop(vecSounds.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Toggle(const int id, bool rewind)
|
||||||
|
{
|
||||||
|
if(ma_sound_is_playing(vecSounds.at(id)))
|
||||||
|
{
|
||||||
|
ma_sound_stop(vecSounds.at(id));
|
||||||
|
|
||||||
|
if(rewind)
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_sound_start(vecSounds.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Seek(const int id, const unsigned long long milliseconds)
|
||||||
|
{
|
||||||
|
unsigned long long frame = (milliseconds * engine.sampleRate) / 1000;
|
||||||
|
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Seek(const int id, const float& location)
|
||||||
|
{
|
||||||
|
unsigned long long length;
|
||||||
|
ma_sound_get_length_in_pcm_frames(vecSounds.at(id), &length);
|
||||||
|
|
||||||
|
unsigned long long frame = length * location;
|
||||||
|
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Forward(const int id, const unsigned long long milliseconds)
|
||||||
|
{
|
||||||
|
unsigned long long cursor;
|
||||||
|
ma_sound_get_cursor_in_pcm_frames(vecSounds.at(id), &cursor);
|
||||||
|
|
||||||
|
unsigned long long frame = (milliseconds * engine.sampleRate) / 1000;
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), cursor + frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::Rewind(const int id, const unsigned long long milliseconds)
|
||||||
|
{
|
||||||
|
unsigned long long cursor;
|
||||||
|
ma_sound_get_cursor_in_pcm_frames(vecSounds.at(id), &cursor);
|
||||||
|
|
||||||
|
unsigned long long frame = (milliseconds * engine.sampleRate) / 1000;
|
||||||
|
ma_sound_seek_to_pcm_frame(vecSounds.at(id), cursor - frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::SetVolume(const int id, const float& volume)
|
||||||
|
{
|
||||||
|
ma_sound_set_volume(vecSounds.at(id), volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::SetPan(const int id, const float& pan)
|
||||||
|
{
|
||||||
|
ma_sound_set_pan(vecSounds.at(id), pan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MiniAudio::SetPitch(const int id, const float& pitch)
|
||||||
|
{
|
||||||
|
ma_sound_set_pitch(vecSounds.at(id), pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long MiniAudio::GetCursorMilliseconds(const int id)
|
||||||
|
{
|
||||||
|
unsigned long long cursor;
|
||||||
|
ma_sound_get_cursor_in_pcm_frames(vecSounds.at(id), &cursor);
|
||||||
|
|
||||||
|
cursor /= sampleRate;
|
||||||
|
cursor /= 1000;
|
||||||
|
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MiniAudio::IsPlaying(const int id)
|
||||||
|
{
|
||||||
|
return ma_sound_is_playing(vecSounds.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
float MiniAudio::GetCursorFloat(const int id)
|
||||||
|
{
|
||||||
|
unsigned long long cursor;
|
||||||
|
ma_sound_get_cursor_in_pcm_frames(vecSounds.at(id), &cursor);
|
||||||
|
|
||||||
|
unsigned long long length;
|
||||||
|
ma_sound_get_length_in_pcm_frames(vecSounds.at(id), &length);
|
||||||
|
|
||||||
|
return (float)cursor / length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<ma_sound*>& MiniAudio::GetSounds() const
|
||||||
|
{
|
||||||
|
return vecSounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<ma_sound*>& MiniAudio::GetOneOffSounds() const
|
||||||
|
{
|
||||||
|
return vecOneOffSounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_device* MiniAudio::GetDevice()
|
||||||
|
{
|
||||||
|
return &device;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_engine* MiniAudio::GetEngine()
|
||||||
|
{
|
||||||
|
return &engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // olc
|
||||||
|
|
||||||
|
#endif
|
6751
include/olcPixelGameEngine.h
Normal file
6751
include/olcPixelGameEngine.h
Normal file
File diff suppressed because it is too large
Load Diff
364
src/main.cpp
Normal file
364
src/main.cpp
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
#include "olcPixelGameEngine.h"
|
||||||
|
#include "olcPGEX_MiniAudio.h"
|
||||||
|
|
||||||
|
|
||||||
|
class OneLoneCoder_Asteroids : public olc::PixelGameEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OneLoneCoder_Asteroids()
|
||||||
|
{
|
||||||
|
sAppName = "Asteroids";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct sSpaceObject
|
||||||
|
{
|
||||||
|
int nSize;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
float angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<sSpaceObject> vecAsteroids;
|
||||||
|
std::vector<sSpaceObject> vecBullets;
|
||||||
|
sSpaceObject player;
|
||||||
|
bool bDead = false;
|
||||||
|
int nScore = 0;
|
||||||
|
|
||||||
|
std::vector<std::pair<float, float>> vecModelShip;
|
||||||
|
std::vector<std::pair<float, float>> vecModelAsteroid;
|
||||||
|
|
||||||
|
std::map<std::string, olc::Renderable*> gfx;
|
||||||
|
std::map<std::string, int> sfx;
|
||||||
|
|
||||||
|
olc::MiniAudio audio;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool OnUserCreate() override
|
||||||
|
{
|
||||||
|
auto loadGraphic = [&](const std::string& key, const std::string& filepath)
|
||||||
|
{
|
||||||
|
olc::Renderable* renderable = new olc::Renderable();
|
||||||
|
renderable->Load(filepath);
|
||||||
|
gfx[key] = renderable;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto loadSound = [&](const std::string& key, const std::string& filepath)
|
||||||
|
{
|
||||||
|
sfx[key] = audio.LoadSound(filepath);
|
||||||
|
};
|
||||||
|
|
||||||
|
loadGraphic("background", "assets/gfx/space.png");
|
||||||
|
|
||||||
|
loadSound("bg-music", "assets/sounds/bg-music.wav");
|
||||||
|
loadSound("laser", "assets/sounds/Laser_Shoot11.wav");
|
||||||
|
loadSound("explosion", "assets/sounds/Explosions1.wav");
|
||||||
|
loadSound("lose", "assets/sounds/lose9.wav");
|
||||||
|
loadSound("thruster", "assets/sounds/thruster.wav");
|
||||||
|
|
||||||
|
vecModelShip =
|
||||||
|
{
|
||||||
|
{ 0.0f, -5.0f},
|
||||||
|
{-2.5f, +2.5f},
|
||||||
|
{+2.5f, +2.5f}
|
||||||
|
}; // A simple Isoceles Triangle
|
||||||
|
|
||||||
|
// Create a "jagged" circle for the asteroid. It's important it remains
|
||||||
|
// mostly circular, as we do a simple collision check against a perfect
|
||||||
|
// circle.
|
||||||
|
int verts = 20;
|
||||||
|
for (int i = 0; i < verts; i++)
|
||||||
|
{
|
||||||
|
float noise = (float)rand() / (float)RAND_MAX * 0.4f + 0.8f;
|
||||||
|
vecModelAsteroid.push_back(std::make_pair(noise * sinf(((float)i / (float)verts) * 6.28318f),
|
||||||
|
noise * cosf(((float)i / (float)verts) * 6.28318f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
backgroundLayer = CreateLayer();
|
||||||
|
EnableLayer(backgroundLayer, true);
|
||||||
|
|
||||||
|
SetDrawTarget(backgroundLayer);
|
||||||
|
DrawSprite(0,0, gfx.at("background")->Sprite());
|
||||||
|
SetDrawTarget(nullptr);
|
||||||
|
|
||||||
|
ResetGame();
|
||||||
|
audio.Play(sfx.at("bg-music"), true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnUserDestroy() override
|
||||||
|
{
|
||||||
|
for(auto it = gfx.begin(); it != gfx.end(); ++it)
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int backgroundLayer = -1;
|
||||||
|
|
||||||
|
void ResetGame()
|
||||||
|
{
|
||||||
|
// Initialise Player Position
|
||||||
|
player.x = ScreenWidth() / 2.0f;
|
||||||
|
player.y = ScreenHeight() / 2.0f;
|
||||||
|
player.dx = 0.0f;
|
||||||
|
player.dy = 0.0f;
|
||||||
|
player.angle = 0.0f;
|
||||||
|
|
||||||
|
vecBullets.clear();
|
||||||
|
vecAsteroids.clear();
|
||||||
|
|
||||||
|
// Put in two asteroids
|
||||||
|
vecAsteroids.push_back({ (int)16, player.x - 80.0f, player.y, 10.0f, 40.0f, 0.0f });
|
||||||
|
vecAsteroids.push_back({ (int)16, player.x + 80.0f, player.y, -10.0f, -40.0f, 0.0f });
|
||||||
|
|
||||||
|
// Reset game
|
||||||
|
bDead = false;
|
||||||
|
nScore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements "wrap around" for various in-game sytems
|
||||||
|
void WrapCoordinates(float ix, float iy, float &ox, float &oy)
|
||||||
|
{
|
||||||
|
ox = ix;
|
||||||
|
oy = iy;
|
||||||
|
if (ix < 0.0f) ox = ix + (float)ScreenWidth();
|
||||||
|
if (ix >= (float)ScreenWidth()) ox = ix - (float)ScreenWidth();
|
||||||
|
if (iy < 0.0f) oy = iy + (float)ScreenHeight();
|
||||||
|
if (iy >= (float)ScreenHeight()) oy = iy - (float)ScreenHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overriden to handle toroidal drawing routines
|
||||||
|
bool Draw(int x, int y, olc::Pixel col = olc::WHITE) override
|
||||||
|
{
|
||||||
|
float fx, fy;
|
||||||
|
WrapCoordinates(x, y, fx, fy);
|
||||||
|
return olc::PixelGameEngine::Draw(fx, fy, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPointInsideCircle(float cx, float cy, float radius, float x, float y)
|
||||||
|
{
|
||||||
|
return sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)) < radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by olcConsoleGameEngine
|
||||||
|
bool OnUserUpdate(float fElapsedTime) override
|
||||||
|
{
|
||||||
|
if (bDead)
|
||||||
|
ResetGame();
|
||||||
|
|
||||||
|
// Clear Screen
|
||||||
|
Clear(olc::BLANK);
|
||||||
|
|
||||||
|
// Steer Ship
|
||||||
|
if (GetKey(olc::LEFT).bHeld)
|
||||||
|
player.angle -= 5.0f * fElapsedTime;
|
||||||
|
if (GetKey(olc::RIGHT).bHeld)
|
||||||
|
player.angle += 5.0f * fElapsedTime;
|
||||||
|
|
||||||
|
// Thrust? Apply ACCELERATION
|
||||||
|
if (GetKey(olc::UP).bHeld)
|
||||||
|
{
|
||||||
|
// ACCELERATION changes VELOCITY (with respect to time)
|
||||||
|
player.dx += sin(player.angle) * 20.0f * fElapsedTime;
|
||||||
|
player.dy += -cos(player.angle) * 20.0f * fElapsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GetKey(olc::UP).bPressed)
|
||||||
|
audio.Play(sfx.at("thruster"), true);
|
||||||
|
|
||||||
|
if(GetKey(olc::UP).bReleased)
|
||||||
|
audio.Stop(sfx.at("thruster"));
|
||||||
|
|
||||||
|
// VELOCITY changes POSITION (with respect to time)
|
||||||
|
player.x += player.dx * fElapsedTime;
|
||||||
|
player.y += player.dy * fElapsedTime;
|
||||||
|
|
||||||
|
// Keep ship in gamespace
|
||||||
|
WrapCoordinates(player.x, player.y, player.x, player.y);
|
||||||
|
|
||||||
|
// Check ship collision with asteroids
|
||||||
|
for (auto &a : vecAsteroids)
|
||||||
|
if (IsPointInsideCircle(a.x, a.y, a.nSize, player.x, player.y))
|
||||||
|
{
|
||||||
|
bDead = true; // Uh oh...
|
||||||
|
audio.Play(sfx.at("lose"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fire Bullet in direction of player
|
||||||
|
if (GetKey(olc::SPACE).bReleased)
|
||||||
|
{
|
||||||
|
vecBullets.push_back({ 0, player.x, player.y, 150.0f * sinf(player.angle), -150.0f * cosf(player.angle), 100.0f });
|
||||||
|
audio.Play(sfx.at("laser"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update and draw asteroids
|
||||||
|
for (auto &a : vecAsteroids)
|
||||||
|
{
|
||||||
|
// VELOCITY changes POSITION (with respect to time)
|
||||||
|
a.x += a.dx * fElapsedTime;
|
||||||
|
a.y += a.dy * fElapsedTime;
|
||||||
|
a.angle += 0.5f * fElapsedTime; // Add swanky rotation :)
|
||||||
|
|
||||||
|
// Asteroid coordinates are kept in game space (toroidal mapping)
|
||||||
|
WrapCoordinates(a.x, a.y, a.x, a.y);
|
||||||
|
|
||||||
|
// Draw Asteroids
|
||||||
|
DrawWireFrameModel(vecModelAsteroid, a.x, a.y, a.angle, (float)a.nSize, olc::YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any new asteroids created after collision detection are stored
|
||||||
|
// in a temporary vector, so we don't interfere with the asteroids
|
||||||
|
// vector iterator in the for(auto)
|
||||||
|
std::vector<sSpaceObject> newAsteroids;
|
||||||
|
|
||||||
|
// Update Bullets
|
||||||
|
for (auto &b : vecBullets)
|
||||||
|
{
|
||||||
|
b.x += b.dx * fElapsedTime;
|
||||||
|
b.y += b.dy * fElapsedTime;
|
||||||
|
WrapCoordinates(b.x, b.y, b.x, b.y);
|
||||||
|
b.angle -= 1.0f * fElapsedTime;
|
||||||
|
|
||||||
|
// Check collision with asteroids
|
||||||
|
for (auto &a : vecAsteroids)
|
||||||
|
{
|
||||||
|
//if (IsPointInsideRectangle(a.x, a.y, a.x + a.nSize, a.y + a.nSize, b.x, b.y))
|
||||||
|
if(IsPointInsideCircle(a.x, a.y, a.nSize, b.x, b.y))
|
||||||
|
{
|
||||||
|
// Asteroid Hit - Remove bullet
|
||||||
|
// We've already updated the bullets, so force bullet to be offscreen
|
||||||
|
// so it is cleaned up by the removal algorithm.
|
||||||
|
b.x = -100;
|
||||||
|
|
||||||
|
// Create child asteroids
|
||||||
|
if (a.nSize > 4)
|
||||||
|
{
|
||||||
|
float angle1 = ((float)rand() / (float)RAND_MAX) * 6.283185f;
|
||||||
|
float angle2 = ((float)rand() / (float)RAND_MAX) * 6.283185f;
|
||||||
|
newAsteroids.push_back({ (int)a.nSize >> 1 ,a.x, a.y, 30.0f * sinf(angle1), 30.0f * cosf(angle1), 0.0f });
|
||||||
|
newAsteroids.push_back({ (int)a.nSize >> 1 ,a.x, a.y, 30.0f * sinf(angle2), 30.0f * cosf(angle2), 0.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove asteroid - Same approach as bullets
|
||||||
|
a.x = -100;
|
||||||
|
nScore += 100; // Small score increase for hitting asteroid
|
||||||
|
audio.Play(sfx.at("explosion"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append new asteroids to existing vector
|
||||||
|
for(auto a:newAsteroids)
|
||||||
|
vecAsteroids.push_back(a);
|
||||||
|
|
||||||
|
// Clear up dead objects - They are out of game space
|
||||||
|
|
||||||
|
// Remove asteroids that have been blown up
|
||||||
|
if (vecAsteroids.size() > 0)
|
||||||
|
{
|
||||||
|
auto i = remove_if(vecAsteroids.begin(), vecAsteroids.end(), [&](sSpaceObject o) { return (o.x < 0); });
|
||||||
|
if (i != vecAsteroids.end())
|
||||||
|
vecAsteroids.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vecAsteroids.empty()) // If no asteroids, level complete! :) - you win MORE asteroids!
|
||||||
|
{
|
||||||
|
// Level Clear
|
||||||
|
nScore += 1000; // Large score for level progression
|
||||||
|
vecAsteroids.clear();
|
||||||
|
vecBullets.clear();
|
||||||
|
|
||||||
|
// Add two new asteroids, but in a place where the player is not, we'll simply
|
||||||
|
// add them 90 degrees left and right to the player, their coordinates will
|
||||||
|
// be wrapped by th enext asteroid update
|
||||||
|
vecAsteroids.push_back({ (int)16, 80.0f * sinf(player.angle - 3.14159f/2.0f) + player.x,
|
||||||
|
80.0f * cosf(player.angle - 3.14159f/2.0f) + player.y,
|
||||||
|
60.0f * sinf(player.angle), 60.0f*cosf(player.angle), 0.0f });
|
||||||
|
|
||||||
|
vecAsteroids.push_back({ (int)16, 80.0f * sinf(player.angle + 3.14159f/2.0f) + player.x,
|
||||||
|
80.0f * cosf(player.angle + 3.14159f/2.0f) + player.y,
|
||||||
|
60.0f * sinf(-player.angle), 60.0f*cosf(-player.angle), 0.0f });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove bullets that have gone off screen
|
||||||
|
if (vecBullets.size() > 0)
|
||||||
|
{
|
||||||
|
auto i = remove_if(vecBullets.begin(), vecBullets.end(), [&](sSpaceObject o) { return (o.x < 1 || o.y < 1 || o.x >= ScreenWidth() - 1 || o.y >= ScreenHeight() - 1); });
|
||||||
|
if (i != vecBullets.end())
|
||||||
|
vecBullets.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Bullets
|
||||||
|
for (auto b : vecBullets)
|
||||||
|
Draw(b.x, b.y);
|
||||||
|
|
||||||
|
// Draw Ship
|
||||||
|
DrawWireFrameModel(vecModelShip, player.x, player.y, player.angle);
|
||||||
|
|
||||||
|
// Draw Score
|
||||||
|
DrawString(2, 2, "SCORE: " + std::to_string(nScore));
|
||||||
|
|
||||||
|
return !GetKey(olc::ESCAPE).bPressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawWireFrameModel(const std::vector<std::pair<float, float>> &vecModelCoordinates, float x, float y, float r = 0.0f, float s = 1.0f, olc::Pixel col = olc::WHITE)
|
||||||
|
{
|
||||||
|
// pair.first = x coordinate
|
||||||
|
// pair.second = y coordinate
|
||||||
|
|
||||||
|
// Create translated model vector of coordinate pairs
|
||||||
|
std::vector<std::pair<float, float>> vecTransformedCoordinates;
|
||||||
|
int verts = vecModelCoordinates.size();
|
||||||
|
vecTransformedCoordinates.resize(verts);
|
||||||
|
|
||||||
|
// Rotate
|
||||||
|
for (int i = 0; i < verts; i++)
|
||||||
|
{
|
||||||
|
vecTransformedCoordinates[i].first = vecModelCoordinates[i].first * cosf(r) - vecModelCoordinates[i].second * sinf(r);
|
||||||
|
vecTransformedCoordinates[i].second = vecModelCoordinates[i].first * sinf(r) + vecModelCoordinates[i].second * cosf(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
for (int i = 0; i < verts; i++)
|
||||||
|
{
|
||||||
|
vecTransformedCoordinates[i].first = vecTransformedCoordinates[i].first * s;
|
||||||
|
vecTransformedCoordinates[i].second = vecTransformedCoordinates[i].second * s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate
|
||||||
|
for (int i = 0; i < verts; i++)
|
||||||
|
{
|
||||||
|
vecTransformedCoordinates[i].first = vecTransformedCoordinates[i].first + x;
|
||||||
|
vecTransformedCoordinates[i].second = vecTransformedCoordinates[i].second + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Closed Polygon
|
||||||
|
for (int i = 0; i < verts + 1; i++)
|
||||||
|
{
|
||||||
|
int j = (i + 1);
|
||||||
|
DrawLine(vecTransformedCoordinates[i % verts].first, vecTransformedCoordinates[i % verts].second,
|
||||||
|
vecTransformedCoordinates[j % verts].first, vecTransformedCoordinates[j % verts].second, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
OneLoneCoder_Asteroids game;
|
||||||
|
if(game.Construct(320, 180, 4, 4))
|
||||||
|
game.Start();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
4
src/olcPGEX_MiniAudio.cpp
Normal file
4
src/olcPGEX_MiniAudio.cpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#define OLC_PGEX_MINIAUDIO
|
||||||
|
#include "olcPGEX_MiniAudio.h"
|
||||||
|
|
||||||
|
|
3
src/olcPixelGameEngine.cpp
Normal file
3
src/olcPixelGameEngine.cpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#define OLC_PGE_APPLICATION
|
||||||
|
#include "olcPixelGameEngine.h"
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user