Initial commit

main
sigonasr2, Sig, Sigo 4 months ago committed by GitHub
commit 278edfcb2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 33
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 20
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 8
      .gitignore
  4. 292
      CMakeLists.txt
  5. 69
      LICENSE
  6. 217
      README.md
  7. 0
      assets/.keepme
  8. BIN
      assets/gfx/space.png
  9. BIN
      assets/sounds/Explosions1.wav
  10. BIN
      assets/sounds/Laser_Shoot11.wav
  11. BIN
      assets/sounds/bg-music.wav
  12. BIN
      assets/sounds/lose9.wav
  13. BIN
      assets/sounds/thruster.wav
  14. 92621
      include/miniaudio.h
  15. 477
      include/olcPGEX_MiniAudio.h
  16. 6751
      include/olcPixelGameEngine.h
  17. 364
      src/main.cpp
  18. 4
      src/olcPGEX_MiniAudio.cpp
  19. 3
      src/olcPixelGameEngine.cpp

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

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

@ -0,0 +1,8 @@
build
linux-build
emscripten-build
nmake-build
mingw-build
vs-build
.vscode
.cache

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

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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,4 @@
#define OLC_PGEX_MINIAUDIO
#include "olcPGEX_MiniAudio.h"

@ -0,0 +1,3 @@
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
Loading…
Cancel
Save