Compare commits

...

42 commits
satsim ... main

Author SHA1 Message Date
Sakimori 46795c54d0 messed around with orbit 2024-02-19 23:12:53 -05:00
Sakimori 92e9981eaf added state writing at configurable time steps 2022-07-05 21:59:29 -04:00
Sakimori 71845520b2
Merge pull request #10 from Sakimori/frontend-base
Frontend base
2022-07-05 19:40:11 -04:00
Sakimori 254bdf2630 a 2022-07-05 15:40:02 -04:00
Sakimori 26f7760758 added env 2022-07-05 15:29:47 -04:00
Sakimori 56811414a9 adjusted border and font 2022-07-05 15:27:52 -04:00
Sakimori 3b48657e4a added consistent border 2022-07-04 21:46:29 -04:00
Sakimori 5db0c879a3 tidyed up css after other changes 2022-07-04 21:16:35 -04:00
Sakimori 1a497e6aba added start page to allow for boot audio 2022-07-04 20:39:46 -04:00
Sakimori f06c0ae64d slick css work 2022-07-04 18:13:41 -04:00
Sakimori 889d2c630e set up key handling for commands.js to process later 2022-07-03 20:43:28 -04:00
Sakimori 63fc945a87 removed tutorial code 2022-07-03 18:45:50 -04:00
Sakimori d754f0e928
Merge pull request #9 from Sakimori/sprited-renders
merging sprited-renders
2022-07-02 22:37:21 -04:00
Sakimori b68c23a7f1 removed duplicate files 2022-07-02 22:31:28 -04:00
Sakimori 7ef54e8de3 boot-up screen active, state change on keypress 2022-07-02 22:30:48 -04:00
Sakimori 5dad42c371 startup page looks neat 2022-07-02 16:58:33 -04:00
Sakimori 6ebada904c initial addition of createreactapp stuff 2022-07-02 12:30:30 -04:00
Sakimori f9dc68559c ground tracks! also fixed a bug with spinny 2022-01-20 17:05:07 -05:00
Sakimori 454475ddec started reporting lat/long on screen during render 2022-01-20 15:19:02 -05:00
Sakimori 8d53f693fd switched to pygame clock management; added flag to save frame to disk 2022-01-20 14:51:17 -05:00
Sakimori d521f3d0a3 ignored test image render file 2022-01-20 14:50:52 -05:00
Sakimori 98921c74cb added initial map base 2022-01-20 14:34:51 -05:00
Sakimori 57d87459c3 planet rendering finished, front/back planes for occlusion done 2022-01-20 00:06:37 -05:00
Sakimori e522f85e23 finished the planet sprite rendering 2022-01-19 21:01:00 -05:00
Sakimori 02ced2dac2 reoriented everything to proper coords, still trying to get sprite size correct 2022-01-19 19:22:00 -05:00
Sakimori 22818f983d initial attempt at sprite-based drawing 2022-01-19 17:41:06 -05:00
Sakimori a540b96c75 added the frames for planet rotation 2022-01-19 15:58:59 -05:00
Sakimori fc138a4cb0 further updates to renderer 2022-01-19 15:19:30 -05:00
Sakimori 95f71c3430 got stationary wireframe sphere ! 2021-06-28 16:00:33 -04:00
Sakimori 6b95683fcd got horizontal stripes working, trying to add a curve to them 2021-06-28 03:51:02 -04:00
Sakimori fb222b6dea added renderImage to camera, to save a representative image of system at any point to disk
takes a long time oops
2021-06-26 22:19:44 -04:00
Sakimori 61562a0bd4 added orbit line 2021-05-02 21:38:42 -04:00
Sakimori 294fd10388 satellite motion and rendering complete 2021-05-02 17:42:54 -04:00
Sakimori 6403e48f22
Update README.md 2021-05-02 13:50:21 -04:00
Sakimori 8969912f3f
Update README.md 2021-05-02 13:32:05 -04:00
Sakimori 3e90ffb5d0 initial class definitions 2021-04-22 15:10:57 -04:00
Sakimori a31dfee4a8 set up ignore for data files and venv 2021-04-22 12:45:30 -04:00
Sakimori 6fe261d731 removed file from tracking 2021-04-22 12:40:09 -04:00
Sakimori c2be5ebd95 created OrbitSim file 2021-04-22 12:28:37 -04:00
Sakimori c16f2c19ad Add project files. 2021-04-22 12:28:37 -04:00
Sakimori efe7e7b24b Add .gitignore and .gitattributes. 2021-04-22 12:28:37 -04:00
Sakimori 880808f487 misc visstudio setup 2021-04-22 12:25:29 -04:00
82 changed files with 16427 additions and 109 deletions

63
.gitattributes vendored Normal file
View file

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

458
.gitignore vendored
View file

@ -1,129 +1,371 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# C extensions
*.so
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Mono auto generated files
mono_crash.*
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Translations
*.mo
*.pot
# Visual Studio 2017 auto generated files
Generated\ Files/
# Django stuff:
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Flask stuff:
instance/
.webassets-cache
# Chutzpah Test files
_Chutzpah*
# Scrapy stuff:
.scrapy
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Sphinx documentation
docs/_build/
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# PyBuilder
target/
# Visual Studio Trace Files
*.e2e
# Jupyter Notebook
.ipynb_checkpoints
# TFS 2012 Local Workspace
$tf/
# IPython
profile_default/
ipython_config.py
# Guidance Automation Toolkit
*.gpState
# pyenv
.python-version
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# TeamCity is a build add-in
_TeamCity*
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# DotCover is a Code Coverage Tool
*.dotCover
# Celery stuff
celerybeat-schedule
celerybeat.pid
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# SageMath parsed files
*.sage.py
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Environments
.env
.venv
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# user files
ConfigFiles/
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
GroundControlFiles/
SatFiles/
/test.png
/bosloo_env

BIN
Assets/Maps/rect_color.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

BIN
Assets/Sphere/0001.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0002.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0003.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0004.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0005.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0006.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0007.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0008.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0009.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0010.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0011.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0012.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0013.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0014.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0015.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0016.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0017.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0018.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0019.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0020.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0021.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0022.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0023.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0025.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0026.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0027.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0028.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0029.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0030.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0031.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0032.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0033.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0034.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0035.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0036.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0037.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0038.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0039.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0040.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0041.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0042.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0043.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0044.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0045.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0046.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0047.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0048.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0049.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
Assets/Sphere/0050.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

143
BoSLOO.pyproj Normal file
View file

@ -0,0 +1,143 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>2bab9fec-2055-4075-95d0-f60299d91bd3</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>OrbitSim.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>BoSLOO</Name>
<RootNamespace>BoSLOO</RootNamespace>
<InterpreterId>MSBuild|BoSLOOenv|$(MSBuildProjectFullPath)</InterpreterId>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="OrbitSim.py" />
<Compile Include="renderer.py">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Interpreter Include="bosloo_env\">
<Id>bosloo_env</Id>
<Version>3.10</Version>
<Description>bosloo_env (Python 3.10 (64-bit))</Description>
<InterpreterPath>Scripts\python.exe</InterpreterPath>
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
<Architecture>X64</Architecture>
</Interpreter>
<Interpreter Include="env\BoSLOOenv\">
<Id>BoSLOOenv</Id>
<Version>3.8</Version>
<Description>BoSLOOenv (Python 3.8 (32-bit))</Description>
<InterpreterPath>Scripts\python.exe</InterpreterPath>
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
<Architecture>X86</Architecture>
</Interpreter>
</ItemGroup>
<ItemGroup>
<Folder Include="Assets\" />
<Folder Include="Assets\Sphere\" />
<Folder Include="GroundControl\" />
<Folder Include="GroundControl\Assets\" />
<Folder Include="GroundControl\frontend\" />
<Folder Include="GroundControl\frontend\public\" />
<Folder Include="GroundControl\frontend\public\Assets\" />
<Folder Include="GroundControl\frontend\public\Assets\image\" />
<Folder Include="GroundControl\frontend\public\Assets\sound\" />
<Folder Include="GroundControl\frontend\src\" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\Sphere\0001.png" />
<Content Include="Assets\Sphere\0002.png" />
<Content Include="Assets\Sphere\0003.png" />
<Content Include="Assets\Sphere\0004.png" />
<Content Include="Assets\Sphere\0005.png" />
<Content Include="Assets\Sphere\0006.png" />
<Content Include="Assets\Sphere\0007.png" />
<Content Include="Assets\Sphere\0008.png" />
<Content Include="Assets\Sphere\0009.png" />
<Content Include="Assets\Sphere\0010.png" />
<Content Include="Assets\Sphere\0011.png" />
<Content Include="Assets\Sphere\0012.png" />
<Content Include="Assets\Sphere\0013.png" />
<Content Include="Assets\Sphere\0014.png" />
<Content Include="Assets\Sphere\0015.png" />
<Content Include="Assets\Sphere\0016.png" />
<Content Include="Assets\Sphere\0017.png" />
<Content Include="Assets\Sphere\0018.png" />
<Content Include="Assets\Sphere\0019.png" />
<Content Include="Assets\Sphere\0020.png" />
<Content Include="Assets\Sphere\0021.png" />
<Content Include="Assets\Sphere\0022.png" />
<Content Include="Assets\Sphere\0023.png" />
<Content Include="Assets\Sphere\0024.png" />
<Content Include="Assets\Sphere\0025.png" />
<Content Include="Assets\Sphere\0026.png" />
<Content Include="Assets\Sphere\0027.png" />
<Content Include="Assets\Sphere\0028.png" />
<Content Include="Assets\Sphere\0029.png" />
<Content Include="Assets\Sphere\0030.png" />
<Content Include="Assets\Sphere\0031.png" />
<Content Include="Assets\Sphere\0032.png" />
<Content Include="Assets\Sphere\0033.png" />
<Content Include="Assets\Sphere\0034.png" />
<Content Include="Assets\Sphere\0035.png" />
<Content Include="Assets\Sphere\0036.png" />
<Content Include="Assets\Sphere\0037.png" />
<Content Include="Assets\Sphere\0038.png" />
<Content Include="Assets\Sphere\0039.png" />
<Content Include="Assets\Sphere\0040.png" />
<Content Include="Assets\Sphere\0041.png" />
<Content Include="Assets\Sphere\0042.png" />
<Content Include="Assets\Sphere\0043.png" />
<Content Include="Assets\Sphere\0044.png" />
<Content Include="Assets\Sphere\0045.png" />
<Content Include="Assets\Sphere\0046.png" />
<Content Include="Assets\Sphere\0047.png" />
<Content Include="Assets\Sphere\0048.png" />
<Content Include="Assets\Sphere\0049.png" />
<Content Include="Assets\Sphere\0050.png" />
<Content Include="GroundControl\frontend\public\Assets\image\BoSLOO logo.txt" />
<Content Include="GroundControl\frontend\public\Assets\image\testMap.png" />
<Content Include="GroundControl\frontend\public\Assets\sound\apricot-rustle-boot.wav" />
<Content Include="GroundControl\frontend\public\Assets\sound\disc-seek-test.mp3" />
<Content Include="GroundControl\frontend\src\BoSLOO logo.json" />
<Content Include="GroundControl\frontend\.gitignore" />
<Content Include="GroundControl\frontend\package-lock.json" />
<Content Include="GroundControl\frontend\package.json" />
<Content Include="GroundControl\frontend\public\favicon.ico" />
<Content Include="GroundControl\frontend\public\index.html" />
<Content Include="GroundControl\frontend\public\logo192.png" />
<Content Include="GroundControl\frontend\public\logo512.png" />
<Content Include="GroundControl\frontend\public\manifest.json" />
<Content Include="GroundControl\frontend\public\robots.txt" />
<Content Include="GroundControl\frontend\README.md" />
<Content Include="GroundControl\frontend\src\commands.js" />
<Content Include="GroundControl\frontend\src\index.css" />
<Content Include="GroundControl\frontend\src\index.js" />
<Content Include="GroundControl\frontend\src\statusbar.js" />
<Content Include="GroundControl\frontend\src\terminal.js" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
the BeforeBuild and AfterBuild targets below. -->
<!--<Target Name="CoreCompile" />-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
</Project>

23
BoSLOO.sln Normal file
View file

@ -0,0 +1,23 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31105.61
MinimumVisualStudioVersion = 10.0.40219.1
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "BoSLOO", "BoSLOO.pyproj", "{2BAB9FEC-2055-4075-95D0-F60299D91BD3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2BAB9FEC-2055-4075-95D0-F60299D91BD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BAB9FEC-2055-4075-95D0-F60299D91BD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BBAD12CA-6246-44EF-80F1-E21768C3AECA}
EndGlobalSection
EndGlobal

23
GroundControl/frontend/.gitignore vendored Normal file
View file

@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View file

@ -0,0 +1,70 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

14709
GroundControl/frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,43 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"babel-runtime": "^6.26.0",
"react": "^18.2.0",
"react-animated-text": "^0.1.4",
"react-clickable-div": "^1.0.0",
"react-dom": "^18.2.0",
"react-keyboard-event-handler": "^1.5.4",
"react-scripts": "5.0.1",
"react-typing-animation": "^1.6.2",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View file

@ -0,0 +1,14 @@
┌──────────┐ ┌─────────┐ ┌─┐ ┌─┬───────┬┐ ┌─┬───────┬┐
│┼┼───────┼│ │┼┼───────┘ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ │┼│ │┼│ ││ │┼│ ││
│┼┼───────┴┘ ┌────────┐ └─┴──────┬┐ │┼│ │┼│ ││ │┼│ ││
│┼│ \\ │┼┼─────┼│ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ \\ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ ┌┐ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼│ ││ │┼│ ││ ││ │┼│ │┼│ ││ │┼│ ││
│┼┼───────┼│ │┼┼─────┼│ ┌────────┼│ │┼┼───────┐ │┼│ ││ │┼│ ││
└──────────┘ └────────┘ └─────────┘ └─────────┘ └─┴───────┴┘ └─┴───────┴┘

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<audio id="boot-sound" src="./Assets/sound/disc-seek-test.mp3">Your browser does not support audio.</audio>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View file

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View file

@ -0,0 +1,3 @@
{
"logo": " ______ _______ _____ _______ _______ \n| __ \\.-----.| __|| |_ | || |\n| __ <| _ ||__ || || - || - |\n|______/|_____||_______||_______||_______||_______|"
}

View file

@ -0,0 +1,68 @@
import Typing from 'react-typing-animation';
import React from 'react';
class Command {
constructor(keyword, fullName) {
this.keyword = keyword;
this.fullName = fullName;
this.helpString = "No help text for this command. Vivian, please be sure to fix this before deploying."
}
call(body) {
return 'This command exists, but does nothing. Vivian, please be sure to fix this before deploying.';
}
}
class helpCommand extends Command{
constructor() {
super('help','help');
this.helpString = "This contains basic help and usage instructions for all commands."
}
call(body) {
if (body === "") {
var commands = "";
for (let command of commandList) {
commands += command.keyword + " ";
}
return (commands);
} else {
for (let command of commandList) {
if (body === command.keyword || body === command.fullName) {
return (command.helpString);
}
}
return ("Unrecognized command. Use without arguments to see full list.")
}
}
}
class loremCommand extends Command {
constructor() {
super('lorem', 'loremipsum');
this.helpString = 'Prints a lorem string.'
}
call(body) {
return ('Space, the final frontier. These are the voyages of the Starship Enterprise. Its five-year mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no man has gone before. Many say exploration is part of our destiny, but it is actually our duty to future generations and their quest to ensure the survival of the human species.');
}
}
const commandList = [new helpCommand(), new loremCommand()];
function sentCommand(sentCommand) {
var commandId = sentCommand.split(" ")[0]
var commandBody = sentCommand.split(" ").slice(1).join(' ')
for (let command of commandList) {
if (commandId === command.keyword || commandId === command.fullName) {
return (<Typing className='typed-line' speed={5}>{command.call(commandBody.trim())}</Typing>);
}
}
return (<Typing className='typed-line' speed={5}>Unrecognized command.</Typing>);
}
export default sentCommand

View file

@ -0,0 +1,126 @@
@import url('https://fonts.googleapis.com/css?family=VT323');
body {
font: 18px "VT323", "Courier New", monospace;
background-color: black;
background-image: radial-gradient(at bottom right, rgb(30 30 30), black);
height: 100vh;
overflow: hidden;
color: #02d300;
text-shadow: 0 0 6px #73ff71;
}
body::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 99vh;
background: repeating-linear-gradient( 0deg, rgb(0 0 0 / 0.20), rgb(0 0 0 / 0.15) 3px, transparent 2px, transparent 6px);
pointer-events: none;
}
::selection{
background: #793d71;
text-shadow: none;
}
.power-on-container {
height: 90vh;
align-items:center;
justify-items:center;
text-align: center;
}
.power-on-box {
position: relative;
justify-self: center;
margin-top: 20vh;
}
#start-text {
font-size: 30px;
border: ridge;
padding: 2em 6em;
box-shadow: 0 0 3px 1px rgb(49 255 0 / 0.70);
}
.console {
padding-top: 15vh;
height: 70vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.logo {
white-space: pre-wrap;
}
.fail-text {
color: #d82222;
text-shadow: 0 0 6px #ff1111;
}
.power-on-self-test{
padding-left: 4em;
}
.terminal-window {
}
.power-on-self-test, .terminal-window {
border:groove;
margin-left: 5vw;
margin-top: -5vh;
padding-bottom: 1em;
padding-right: 2em;
width: 60vw;
overflow-y: auto;
overflow-x: hidden;
flex-grow: 1;
display: flex;
flex-direction: column-reverse;
box-sizing: border-box;
box-shadow: 0 0 3px 1px rgb(49 255 0 / 0.70);
}
.terminal{
}
.active-line{
outline: none;
width: 2em;
resize:horizontal;
}
.blink-text {
animation: blinker 1s step-start infinite;
}
.typed-line{
display: inline;
}
.terminal-line th{
text-align: right;
vertical-align: top;
padding-right: 0.2em;
width: 4em;
}
.terminal-line td{
text-align: left;
}
@keyframes blinker {
50% {
opacity: 0;
}
}

View file

@ -0,0 +1,98 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import Typing from 'react-typing-animation';
import ClickableDiv from 'react-clickable-div';
import KeyboardEventHandler from 'react-keyboard-event-handler'
import './index.css';
import logos from './BoSLOO logo.json';
import Terminal from './terminal.js';
import StatusBar from './statusbar.js';
const nominal = <Terminal />;
class Console extends React.Component {
constructor(props) {
super(props);
this.swapper = this.swapper.bind(this);
this.state = {
bodyObj: <PowerOn onClick={this.swapper} />,
init: 0,
}
}
swapper(key, e) {
if (this.state.init === 0) {
this.replaceBody(<SelfTest />);
this.playSound();
} else if (this.state.init === 1) {
this.replaceBody(nominal);
}
this.setState({ init: this.state.init + 1 });
}
appendToBody(newContent) {
let bodyObj = JSON.parse(JSON.stringify(this.state.bodyObj)) + newContent;
this.setState({
bodyObj: bodyObj
});
}
replaceBody(newContent) {
this.setState({
bodyObj: newContent
});
}
playSound() {
var sound = document.getElementById("boot-sound")
sound.volume = 0.1;
sound.play();
}
render() {
return (
<div className='console'>
<KeyboardEventHandler handleKeys={['all']} onKeyEvent={this.swapper} />
{this.state.bodyObj}
{this.state.init >= 2 ? <StatusBar/> : null}
</div>
);
}
}
class SelfTest extends React.Component {
constructor(props) {
super(props);
this.state = {
logodisplay: false
}
}
render() {
const final = <span className='logo'>{logos.logo} < br /><br /><br /><Typing speed={5}>Press any key to continue...<br /><span>{'>'} <span className='blink-text'>_</span></span></Typing></span>;
return (
<div className='power-on-self-test'>
{this.state.logodisplay ? final : null}
<Typing speed={30} onFinishedTyping={() => this.setState({ logodisplay: true })}>
BoSLOO ACPI BIOS v0.1<br />
Sakimori Ind. 2022<br />
<Typing.Speed ms={ 5}/>Initializing cache.................................<Typing.Speed ms={200} />...<Typing.Speed ms={5} /> OK!<br />
Initializing network.........<Typing.Speed ms={500} />....<Typing.Speed ms={5} />.................<Typing.Speed ms={300} />....<Typing.Speed ms={5} /> OK!<br />
Initializing GPU...................................<Typing.Speed ms={1000} />...<Typing.Speed ms={5} /> <span className='fail-text'>FAIL!</span><br />
<br />
</Typing>
</div>
)
}
}
function PowerOn(props) {
return (
<div className="power-on-container"><div className='power-on-box'><span id='start-text' onClick={props.onClick}><span className='blink-text'>START</span></span></div></div>
);
}
// =========================================
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Console />);

View file

@ -0,0 +1,9 @@
import React from 'react';
class StatusBar extends React.Component {
render() {
return null;
}
}
export default StatusBar

View file

@ -0,0 +1,100 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import * as KeyboardEventHandler from 'react-keyboard-event-handler';
import sentCommand from './commands.js'
class Terminal extends React.Component {
constructor(props) {
super(props);
this.state = {
lines: [<tr className='terminal-line' key={-20}><th>-20</th><td>Welcome to BoSLOO Ground Control Console.</td></tr>, <tr className='terminal-line' key={-10}><th>-10</th><td> Time of connection: {new Date().toLocaleString('en-US')}</td></tr>],
lastLine : '',
waitForUser: false,
lineNumber: 0,
controlHeld: false,
};
this.charIn = this.charIn.bind(this);
this.handleKey = this.handleKey.bind(this);
const window = document.getRootNode();
window.addEventListener('paste', (e) => {
e.preventDefault();
let paste = (e.clipboardData || window.clipboardData).getData('text');
this.appendText(paste);
});
}
addLines(newLinesArray) {
let currLines = this.state.lines
this.setState({
lines: currLines.concat(newLinesArray),
});
}
addCharacter(newChar) {
this.setState({
lastLine: JSON.parse(JSON.stringify(this.state.lastLine)) + newChar,
});
}
appendText(newText) {
this.setState({
lastLine: JSON.parse(JSON.stringify(this.state.lastLine)) + newText,
});
}
deleteCharacter() {
this.setState({
lastLine: this.state.lastLine.slice(0,-1),
});
}
finishLine() {
let commandBody = sentCommand(this.state.lastLine);
this.addLines([<tr className='terminal-line' key={this.state.lineNumber}><th>{this.state.lineNumber}</th><td>{'>'}{this.state.lastLine}</td></tr>,
<tr className='terminal-line' key={this.state.lineNumber + 10}><th>{this.state.lineNumber + 10}</th><td>{commandBody}</td></tr>]);
this.setState({ lastLine: '', lineNumber: this.state.lineNumber+20 });
}
charIn(newCharObj) {
this.setState({
lastLine: newCharObj.target.value,
});
}
handleKey(key, e) {
if (e.key === 'Enter') {
this.finishLine();
} else if (e.keyCode === 8) { /*backspace*/
this.deleteCharacter();
} else if (e.ctrlKey) {
return;
} else if (e.keyCode === 32) {
this.addCharacter(' ');
} else if (e.keyCode >= 40) {
this.addCharacter(e.key);
}
}
displayLines() {
return this.state.lines;
}
render() {
return (
<div className='terminal-window'>
<table className='terminal'>
<tbody>
<KeyboardEventHandler handleKeys={['all']} onKeyEvent={this.handleKey} />
{this.displayLines()}
<tr className='terminal-line'><th>{this.state.lineNumber}</th><td>{'>'}{this.state.lastLine}<span className='blink-text'>_</span></td></tr>
</tbody>
</table>
</div>
)
}
}
export default Terminal

224
OrbitSim.py Normal file
View file

@ -0,0 +1,224 @@
import os, json, numpy, pygame, time, threading, jsonpickle
from renderer import *
from copy import deepcopy
groundControlPath = "GroundControl"
stateFilePath = os.path.join("SatState.json")
configPath = os.path.join("ConfigFiles", "OrbitSim")
configFilename = os.path.join(configPath, "Universe.cfg")
satSavePath = os.path.join(configPath, "Orbit.cfg")
mapFilename = os.path.join(configPath, "Map.png")
STATE_EVENT = pygame.event.custom_type()
def config():
"""Returns the config dictionary. Generates with default values if no config dictionary exists."""
if not os.path.exists(configPath):
os.makedirs(configPath)
if not os.path.exists(configFilename):
#generate default
config_dic = {
"G": 6.674e-11,
"earthMass": 5.972e24, #in kg
"earthRadius": 6378000, #meters
"timeScale": 1, #higher number go faster wheeeeee
"updateTick": 300 #seconds to wait between save to file
}
with open(configFilename, "w") as file:
json.dump(config_dic, file, indent = 4)
return config_dic
else:
with open(configFilename) as file:
return json.load(file)
class OrbitingBody:
"""a zero-mass point object parented to a planet"""
def __init__(self, location:Point, velocity:Point, name, displaySize, parentPlanet):
self.location = location
self.resetLocation = location.copy()
self.velocity = velocity
self.resetVelocity = velocity.copy()
self.name = name
self.displaySize = displaySize #the size of the object on camera in pixels, for visibility reasons
self.parentPlanet = parentPlanet
self.lastDelta = 0
self.lastSecondDelta = 0
self.keepFreeze = 3
def stationKeep(self):
currDelta = Point.subtract(self.resetLocation, self.location).magnitude()
currSecondDelta = currDelta - self.lastDelta
if (currSecondDelta > 0) and (self.lastSecondDelta <= 0) and self.keepFreeze <= 0:
self.location = self.resetLocation.copy()
self.velocity = self.resetVelocity.copy()
self.keepFreeze = 3
elif self.keepFreeze > 0:
self.keepFreeze -= 1
self.lastDelta = currDelta
self.lastSecondDelta = currSecondDelta
def latLongAlt(self):
rho, theta, phi = self.location.polar()
rawLat, rawLong = self.parentPlanet.sphericalToLatLong(theta, phi) #negative lat is north, positive lat is south, positive long is east, negative long is west
return (rho - self.parentPlanet.radius), rawLat, rawLong
def writeStateReadable(self):
alt, lat, long = self.latLongAlt()
stateDic = {
"notes": "lat: pos S, neg N; long: pos E, neg W",
"latitude": lat,
"longitude": long,
"altitude": alt,
"velocity": self.velocity.magnitude()
}
with open(stateFilePath, "w") as file:
json.dump(stateDic, file, indent=4)
def saveState(self):
stateDic = {
"location": jsonpickle.encode(self.location),
"velocity": jsonpickle.encode(self.velocity),
}
def loadState(self):
if os.path.exists(satSavePath):
with open(satSavePath) as file:
state = json.load(file)
self.location = jsonpickle.decode(state["location"])
self.velocity = jsonpickle.decode(state["velocity"])
return True
else:
return False
class Planet:
"""A massive body at 0,0,0 and a given radius."""
def __init__(self, name, mass, radius, rotationPeriod, location:Point = deepcopy(Point.zero)):
"""Rotation period given in seconds."""
self.location = location
self.name = name
self.mass = mass
self.radius = radius
self.rotationPercentage = 0.00
self.rotationPeriod = rotationPeriod
def rotate(self, timeDelta):
self.rotationPercentage += timeDelta*100/self.rotationPeriod
if self.rotationPercentage >= 100.0:
self.rotationPercentage -= 100.0
def sphericalToLatLong(self, theta, phi):
"""Converts theta and phi spherical coordinates to latitude and longitude. -> lat, long"""
rotRadian = self.rotationPercentage/100 * 2 * math.pi
lat = math.degrees(phi - (math.pi/2)) #negative lat is north, positive is south
long = rotRadian - theta #positive long is east, negative is west
if long < -math.pi:
long += math.pi*2
elif long > math.pi:
long -= math.pi*2
return (lat, math.degrees(long))
class DisplayPoint:
"""A single point of any color"""
def __init__(self, location, color):
self.location = location
self.color = color
class DecayPoint(DisplayPoint):
"""A display point that slowly fades to black"""
decayTick = 1
currentDecayTick = 0
color = (255,255,255,255)
def update(self):
self.currentDecayTick += 1
if self.currentDecayTick >= self.decayTick:
self.currentDecayTick = 0
self.color = (self.color[0], self.color[1], self.color[2], (max((self.color[3]-5, 0))))
def copy(self):
"""returns a distinct copy of the point"""
return DecayPoint(self.location, self.color)
Planet.Earth = Planet("Earth", config()["earthMass"], config()["earthRadius"], 86400)
def physicsUpdate(objects, orbitlines, deltaTime):
"""updates the positions of all orbiting objects in [objects] with timestep deltaTime"""
for obj in objects:
if type(obj).__name__ == "OrbitingBody":
orbitlines.append(DecayPoint(deepcopy(obj.location), (255,255,255,255)))
if len(orbitlines) > 100:
orbitlines.pop(0)
accel = Point.scalarMult(Point.subtract(obj.location, obj.parentPlanet.location).normalize(),-(config()["G"] * obj.parentPlanet.mass)/(Point.subtract(obj.location, obj.parentPlanet.location).magnitude() ** 2))
obj.velocity = Point.add(obj.velocity, Point.scalarMult(accel, deltaTime))
obj.location = Point.add(obj.location, Point.scalarMult(obj.velocity, deltaTime))
obj.stationKeep()
elif type(obj).__name__ == "Planet":
obj.rotate(deltaTime)
for line in orbitlines:
line.update()
if __name__=="__main__":
pygame.init()
pygame.display.set_caption("Spinny")
window = pygame.display.set_mode((900, 900))
resolutionDownscaling = 2
pygame.display.flip()
FPS = 144 #max framerate
frameTime = 1/144
running = True
display = False
thisEarth = deepcopy(Planet.Earth)
sat = OrbitingBody(Point(0, config()["earthRadius"]*5, config()["earthRadius"]*2), Point(-2500,0,0), "BoSLOO", 5, thisEarth)
orbitlines = []
renderObjects = [thisEarth, sat, orbitlines]
configFile = config()
clock = pygame.time.Clock()
stateTimer = pygame.time.set_timer(STATE_EVENT, configFile["updateTick"]*1000)
mapThread = threading.Thread()
save = False
clock.tick(FPS)
while running:
clock.tick(FPS)
if display:
#deltaTime = frameTime * config()["timeScale"]
deltaTime = (clock.get_time()/1000) * configFile["timeScale"]
physicsUpdate(renderObjects, orbitlines, deltaTime)
camera.renderFrame(save=save)
save=False
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if not display:
display = True
camera = Camera(window, Point(10 * configFile["earthRadius"], 0, 0), thisEarth, renderObjects)
camera.renderFrame()
pygame.display.flip()
else:
save = True
if not mapThread.is_alive():
mapThread = threading.Thread(target=camera.saveGroundTrack())
mapThread.start()
elif event.type == STATE_EVENT:
sat.writeStateReadable()
configFile = config()
#time.sleep(frameTime)
pygame.quit()
print("Bye!")

View file

@ -2,7 +2,7 @@
Browser-based MMO Satellite Toy/Idle Game
### Glossary: **This is incomplete and will be added to as we go**
## Glossary: **This is incomplete and will be added to as we go**
@ -19,3 +19,13 @@ Ground station -> Any given researcher's UI in browser, and any upgrades they ma
Missions -> Research tasks that will result in government funding + grants
Funding -> The amount of cash available to use to upgrade a user's ground station/schedule sensor time.
## Constants:
G: 6.674 * 10^-11
M🜨: 5.972 * 10^24 kg
R🜨: 6378000 m
Period of Rotation(🜨): 86400

7
SatState.json Normal file
View file

@ -0,0 +1,7 @@
{
"notes": "lat: pos S, neg N; long: pos E, neg W",
"latitude": -12.808893957460064,
"longitude": 140.55873504072275,
"altitude": 19134253.574575923,
"velocity": 3777.2583558704296
}

BIN
example.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

271
renderer.py Normal file
View file

@ -0,0 +1,271 @@
import numpy, pygame, math, os
import pygame.freetype
ASSET_DIR = "Assets"
SPHERE_FOLDER_NAME = "Sphere"
MAPS_FOLDER_NAME = "Maps"
class Point:
"""Numpy 3-vec"""
def __init__(self, x, y, z):
self.vector = numpy.array([x, y, z])
def copy(self):
return Point(self.vector[0], self.vector[1], self.vector[2])
def polar(self):
"""Converts the vector rectangular coordinates to polar coordinates."""
if self.vector[0] == 0:
self.vector[0] = 0.1
if self.vector[2] == 0:
self.vector[2] = 0.1
rho = math.sqrt(int(self.vector[0]) ** 2 + int(self.vector[1]) ** 2 + int(self.vector[2]) ** 2)
theta = math.atan(self.vector[1]/self.vector[0]) #this has a range of -pi/2 to pi/2 but we need 0 to 2pi so more work needed
phi = math.acos(self.vector[2]/rho)
if self.vector[0] < 0:
if self.vector[1] >= 0: #if x is positive, atan is fine. need to check if x is negative, first.
theta += math.pi
else:
theta -= math.pi
return [rho, theta, phi]
def magnitude(self):
return float(numpy.linalg.norm(self.vector))
def normalize(self):
self.vector = self.vector/self.magnitude()
return self
def distanceFromPoint(self, otherPoint:"Point"):
return numpy.linalg.norm(self.vector - otherPoint.vector)
def distanceFromLine(self, line:"Line"):
return numpy.linalg.norm(numpy.cross(line.p2.vector - line.p1.vector, self.vector - line.p1.vector)/numpy.linalg.norm(line.p2.vector - line.p1.vector))
def add(p1, p2):
sum = numpy.add(p1.vector, p2.vector)
return Point(sum[0], sum[1], sum[2])
def subtract(p1, p2):
diff = numpy.subtract(p1.vector, p2.vector)
return Point(diff[0], diff[1], diff[2])
def dot(p1, p2):
return numpy.dot(p1.vector, p2.vector)
def scalarMult(p1, scalar):
mult = p1.vector * scalar
return Point(mult[0], mult[1], mult[2])
Point.zero = Point(0, 0, 0)
class Ray:
def __init__(self, origin:Point, direction:Point):
self.origin = origin
self.direction = direction
class Line:
def __init__(self, p1:Point, p2:Point):
self.p1 = p1
self.p2 = p2
def intersectWithPlane(self, plane):
lineVec = Point.subtract(self.p2, self.p1)
dot = Point.dot(plane.normal, lineVec)
if abs(dot) > 1e-6:
w = Point.subtract(self.p1, plane.point)
fac = -Point.dot(plane.normal, w) / dot
u = Point.scalarMult(lineVec, fac)
return Point.add(self.p1, u)
else:
return None
class Plane:
def __init__(self, point:Point, normal:Point):
self.point = point
self.normal = normal
class PlanetSprite(pygame.sprite.Sprite):
def __init__(self, camera, parentPlanet:"Planet"):
pygame.sprite.Sprite.__init__(self)
#the rotation animation loops every 64th of a rotation, so determine and store the frame number.
self.frames = {}
for imgName in os.listdir(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME)):
if imgName.endswith(".png"):
self.frames[imgName.strip(".png")] = pygame.image.load(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME, imgName)).convert_alpha()
self.parentPlanet = parentPlanet
self.frameNumber = str(round(math.modf(self.parentPlanet.rotationPercentage/100 * 64)[0] * 49) + 1).zfill(4)
self.image = self.frames[self.frameNumber]
self.setSize(camera)
def setSize(self, camera):
winWidth, winHeight = camera.surface.get_size()
#distance = Point.subtract(camera.location, self.parentPlanet.location).magnitude()
#radius = self.parentPlanet.radius
#self.sideLength = int((1/math.tan(numpy.radians(camera.hFOV)/2))*radius/math.sqrt(distance**2 - radius**2)*winWidth/2)
lineToCam = Line(Point.add(self.parentPlanet.location, Point(0, self.parentPlanet.radius,0)), camera.location)
intersectPoint = lineToCam.intersectWithPlane(camera.screenPlane)
radius = intersectPoint.vector[1]
self.sideLength = int(radius*2*600/530)
self.image = pygame.transform.scale(self.image, (self.sideLength, self.sideLength))
self.rect = self.image.get_rect()
self.rect.center = (winWidth/2, winHeight/2)
def update(self):
self.frameNumber = str(round(math.modf(self.parentPlanet.rotationPercentage/100 * 64)[0] * 49) + 1).zfill(4)
self.image = pygame.image.load(os.path.join(ASSET_DIR, SPHERE_FOLDER_NAME, f"{self.frameNumber}.png")).convert_alpha()
if self.sideLength is not None:
self.image = pygame.transform.scale(self.image, (self.sideLength, self.sideLength))
class Camera:
"""Object in charge of rendering both the realtime 3D scene and a ground track map."""
def __init__(self, surface:pygame.Surface, location:Point, target:"Planet", objects, hFOV = 60):
self.surface = surface
self.objects = objects
self.location = location
self.target = target
self.hFOV = hFOV
self.spriteGroup = pygame.sprite.Group()
self.pastTrackPoints = []
self.trackSampleRate = 8
self.trackSampleCount = 0
self.mapSurface = pygame.image.load(os.path.join(ASSET_DIR, MAPS_FOLDER_NAME, "rect_color.png"))
self.mapWidth, self.mapHeight = self.mapSurface.get_size()
winWidth, winHeight = self.surface.get_size()
winDistance = winWidth / (2 * math.tan(numpy.radians(self.hFOV/2))) #distance for a virtual screen to exist in-space to give the correct FOV
vecToCenter = Point.subtract(self.target.location, self.location)
vecToCenter.normalize()
self.screenPlane = Plane(Point.add(self.location, Point.scalarMult(vecToCenter, winDistance)), vecToCenter)
self.spriteGroup.add(PlanetSprite(self, self.target))
def isInside(self, planet:"Planet"):
"""returns True if camera is inside the planet."""
return numpy.linalg.norm(self.location.magnitude) < planet.radius
def renderFrame(self, save=False):
"""generates a frame and draws it to the surface. Does not update screen; use pygame.display.flip()"""
font = pygame.freetype.SysFont("Comic Sans MS", 14)
winWidth, winHeight = self.surface.get_size()
frontSurface = pygame.Surface((winWidth, winHeight), pygame.SRCALPHA)
backSurface = pygame.Surface((winWidth, winHeight), pygame.SRCALPHA)
backgroundSurface = pygame.Surface((winWidth, winHeight))
backgroundSurface.fill((15,15,15))
backSurface.fill((0,0,0,0))
frontSurface.fill((0,0,0,0))
#pygame uses 0,0 as the top left corner
for obj in self.objects:
if type(obj).__name__ == "OrbitingBody":
sat = obj
lineToCamera = Line(obj.location, self.location)
intersectPoint = lineToCamera.intersectWithPlane(self.screenPlane)
intersectPoint.vector[2] = -intersectPoint.vector[2]
if intersectPoint is not None:
intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2))) #x is meaningless here
if sat.location.vector[0] < 0:
drawSurface = backSurface
else:
drawSurface = frontSurface
pygame.draw.circle(drawSurface, (255,255,150,255), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), obj.displaySize)
elif isinstance(obj, list):
for orbitline in obj:
if orbitline.color != (0,0,0):
lineToCamera = Line(orbitline.location, self.location)
intersectPoint = lineToCamera.intersectWithPlane(self.screenPlane)
intersectPoint.vector[2] = -intersectPoint.vector[2]
if intersectPoint is not None:
intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
if orbitline.color[3] != 0:
if orbitline.location.vector[0] < 0:
drawSurface = backSurface
else:
drawSurface = frontSurface
pygame.draw.circle(drawSurface, orbitline.color, (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 1)
#DEBUG DOTS
#lineToCam = Line(Point.add(self.target.location, Point(0,self.target.radius,0)), self.location)
#intersectPoint = lineToCam.intersectWithPlane(self.screenPlane)
#intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
#pygame.draw.circle(frontSurface, (255,150,150,255), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 5)
#newLineToCam = Line(Point.add(self.screenPlane.point, Point(0,750,0)), self.location)
#intersectPoint = newLineToCam.intersectWithPlane(self.screenPlane)
#intersectPoint = Point.add(intersectPoint, Point(0, int(winWidth/2), int(winHeight/2)))
#pygame.draw.circle(screenSurface, (150,255,150), (int(intersectPoint.vector[1]), int(intersectPoint.vector[2])), 5)
#generate text
alt, rawLat, rawLong = sat.latLongAlt()
self.updateTrackList(rawLat, rawLong)
latString = f"Latitude: {round(rawLat,4)}⁰ S" if rawLat >= 0 else f"Latitude: {-round(rawLat,4)}⁰ N"
longString = f"Longitude: {round(rawLong,4)}⁰ E" if rawLong >= 0 else f"Longitude: {-round(rawLong,4)}⁰ W"
font.render_to(backSurface, (0,0), f"Speed: {round(sat.velocity.magnitude()/1000,3)} km/s", (255,255,255))
font.render_to(backSurface, (0,20), f"Altitude: {round((alt)/1000)} km", (255,255,255))
font.render_to(backSurface, (0,50), latString, (255,255,255))
font.render_to(backSurface, (0,70), longString, (255,255,255))
self.spriteGroup.update()
self.spriteGroup.draw(backSurface)
self.surface.blit(backgroundSurface, (0,0))
self.surface.blit(backSurface, (0,0))
self.surface.blit(frontSurface, (0,0))
if save:
pygame.image.save(self.surface, "test.png")
def updateTrackList(self, lat, long):
"""Updates the ground track map list of points."""
if self.trackSampleCount != self.trackSampleRate:
self.trackSampleCount += 1
return
if len(self.pastTrackPoints) > 20000:
self.pastTrackPoints.pop(0)
#latitude is from -90 to 90; longitude is from -180 to 180.
latPercent = (lat + 90)/180
longPercent = (long + 180)/360
lat = self.mapHeight * latPercent
long = self.mapWidth * longPercent
self.pastTrackPoints.append((long, lat))
self.trackSampleCount = 0
def saveGroundTrack(self):
mapSurface = pygame.Surface.copy(self.mapSurface)
sets = []
currStart = 0
for i in range(1,len(self.pastTrackPoints)):
if abs(self.pastTrackPoints[i][0] - self.pastTrackPoints[i-1][0]) > 400:
sets.append(self.pastTrackPoints[currStart:i])
currStart = i
sets.append(self.pastTrackPoints[currStart:])
colors = [(122,255,243), (211,122,255), (222,0,177)]
for i in range(0,len(sets)):
try:
pygame.draw.lines(mapSurface, colors[i%3], False, sets[i], width=5)
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long, lat+1) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long+1, lat) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long, lat-1) for long, lat in sets[i]])
#pygame.draw.aalines(mapSurface, colors[i%3], False, [(long-1, lat) for long, lat in sets[i]])
except:
pass
pygame.image.save(mapSurface, "testMap.png")

BIN
testMap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB