Compare commits
30 Commits
main
...
feat/netwo
Author | SHA1 | Date | |
---|---|---|---|
1b1d9dcdac | |||
2565617ff9 | |||
01668c7be3 | |||
cafbc55780 | |||
ea3c4a2d2a | |||
89b756a615 | |||
6af84bcb6d | |||
3c1528d879 | |||
6f3e7b4ae5 | |||
86ef57fb62 | |||
6c326b1fc6 | |||
b8b10de08a | |||
edd2dd8511 | |||
70ac012a83 | |||
d5a904fe8f | |||
b1582ab5c2 | |||
8a0a0289f9 | |||
776d029e7e | |||
5afb8b69bf | |||
65073ec1ca | |||
0d62e5c986 | |||
fe5a08840c | |||
1c7b1cb78a | |||
78010c266e | |||
ef8b04648c | |||
d4c57c0153 | |||
0e198afeab | |||
de267a9d0f | |||
977a2abdd7 | |||
91e88bbff8 |
27
.vscode/launch.json
vendored
Normal file
27
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Game/bin/Debug/net8.0/Game.dll",
|
||||
"args": ["server"],
|
||||
"cwd": "${workspaceFolder}/Game",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"AABB",
|
||||
"DAABB",
|
||||
"Syntriax"
|
||||
]
|
||||
}
|
18
.vscode/tasks.json
vendored
Normal file
18
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "dotnet",
|
||||
"task": "build",
|
||||
"problemMatcher": ["$msCompile"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"label": "build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/Game"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
2
Engine
2
Engine
@ -1 +1 @@
|
||||
Subproject commit 9e4c74ed1d73eac40ed29fbdb1e5103c121844a9
|
||||
Subproject commit 2cf6135063b12dfff4d2c8391ad8edde806183f0
|
@ -3,31 +3,31 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-mgcb": {
|
||||
"version": "3.8.2.1105",
|
||||
"version": "3.8.1.303",
|
||||
"commands": [
|
||||
"mgcb"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor": {
|
||||
"version": "3.8.2.1105",
|
||||
"version": "3.8.1.303",
|
||||
"commands": [
|
||||
"mgcb-editor"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-linux": {
|
||||
"version": "3.8.2.1105",
|
||||
"version": "3.8.1.303",
|
||||
"commands": [
|
||||
"mgcb-editor-linux"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-windows": {
|
||||
"version": "3.8.2.1105",
|
||||
"version": "3.8.1.303",
|
||||
"commands": [
|
||||
"mgcb-editor-windows"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-mac": {
|
||||
"version": "3.8.2.1105",
|
||||
"version": "3.8.1.303",
|
||||
"commands": [
|
||||
"mgcb-editor-mac"
|
||||
]
|
968
.gitignore → Game/.gitignore
vendored
968
.gitignore → Game/.gitignore
vendored
@ -1,484 +1,484 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from `dotnet new gitignore`
|
||||
|
||||
# dotenv files
|
||||
.env
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# 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/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# 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
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# Tye
|
||||
.tye/
|
||||
|
||||
# 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
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# 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 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# 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/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# 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
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea
|
||||
|
||||
##
|
||||
## Visual studio for Mac
|
||||
##
|
||||
|
||||
|
||||
# globs
|
||||
Makefile.in
|
||||
*.userprefs
|
||||
*.usertasks
|
||||
config.make
|
||||
config.status
|
||||
aclocal.m4
|
||||
install-sh
|
||||
autom4te.cache/
|
||||
*.tar.gz
|
||||
tarballs/
|
||||
test-results/
|
||||
|
||||
# Mac bundle stuff
|
||||
*.dmg
|
||||
*.app
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Vim temporary swap files
|
||||
*.swp
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from `dotnet new gitignore`
|
||||
|
||||
# dotenv files
|
||||
.env
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# 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/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# 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
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# Tye
|
||||
.tye/
|
||||
|
||||
# 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
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# 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 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# 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/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# 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
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea
|
||||
|
||||
##
|
||||
## Visual studio for Mac
|
||||
##
|
||||
|
||||
|
||||
# globs
|
||||
Makefile.in
|
||||
*.userprefs
|
||||
*.usertasks
|
||||
config.make
|
||||
config.status
|
||||
aclocal.m4
|
||||
install-sh
|
||||
autom4te.cache/
|
||||
*.tar.gz
|
||||
tarballs/
|
||||
test-results/
|
||||
|
||||
# Mac bundle stuff
|
||||
*.dmg
|
||||
*.app
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Vim temporary swap files
|
||||
*.swp
|
8
Game/Abstract/IContentLoader.cs
Normal file
8
Game/Abstract/IContentLoader.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public interface IMonoGameContentLoader
|
||||
{
|
||||
void LoadContent(ContentManager content);
|
||||
}
|
120
Game/Behaviours/BallBehaviour.cs
Normal file
120
Game/Behaviours/BallBehaviour.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
using LiteNetLib;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Network;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
using Syntriax.Engine.Physics2D;
|
||||
using Syntriax.Engine.Physics2D.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class BallBehaviour : NetworkBehaviour, IMonoGameContentLoader
|
||||
{
|
||||
public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
|
||||
public float Speed { get; set; } = 500f;
|
||||
public float SpeedUpMultiplier { get; set; } = .0125f;
|
||||
|
||||
private readonly Random random = new();
|
||||
private IRigidBody2D rigidBody = null!;
|
||||
private INetworkCommunicator communicator = null!;
|
||||
private SoundEffect soundEffect = null!;
|
||||
|
||||
public void LoadContent(ContentManager content)
|
||||
{
|
||||
soundEffect = content.Load<SoundEffect>("Hit");
|
||||
}
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? foundRigidBody))
|
||||
throw new Exception($"{nameof(IRigidBody2D)} is missing on {GameObject.Name}.");
|
||||
if (!BehaviourController.TryGetBehaviour(out ICollider2D? foundCollider))
|
||||
throw new Exception($"{nameof(ICollider2D)} is missing on {GameObject.Name}.");
|
||||
if (!GameObject.GameManager.TryFindBehaviour(out INetworkCommunicator? foundCommunicator))
|
||||
throw new Exception($"{nameof(INetworkCommunicator)} is missing on GameManager.");
|
||||
|
||||
foundCollider.OnCollisionDetected += OnCollisionDetected;
|
||||
|
||||
rigidBody = foundRigidBody;
|
||||
communicator = foundCommunicator;
|
||||
if (GameObject.GameManager.TryFindBehaviour(out PongManagerBehaviour? pongManager))
|
||||
{
|
||||
pongManager.OnReset += ResetBall;
|
||||
pongManager.OnScored += ResetBall;
|
||||
pongManager.OnFinished += DisableBall;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableBall(PongManagerBehaviour pongManager)
|
||||
{
|
||||
BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
|
||||
rigidBody.Velocity = Vector2D.Zero;
|
||||
}
|
||||
|
||||
private void ResetBall(PongManagerBehaviour pongManager)
|
||||
{
|
||||
StateEnable.Enabled = true;
|
||||
BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
|
||||
rigidBody.Velocity = GetRandomDirection() * Speed;
|
||||
|
||||
SendBallData();
|
||||
}
|
||||
|
||||
private Vector2D GetRandomDirection()
|
||||
{
|
||||
const float AllowedRadians = 45f * Syntriax.Engine.Core.Math.DegreeToRadian;
|
||||
float rotation = (float)random.NextDouble() * 2f * AllowedRadians - AllowedRadians;
|
||||
bool isBackwards = (random.Next() % 2) == 1;
|
||||
return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation);
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
|
||||
return;
|
||||
|
||||
Vector2D speedUp = rigidBody.Velocity.Normalized * Time.DeltaTimeFrame;
|
||||
rigidBody.Velocity += speedUp * SpeedUpMultiplier;
|
||||
}
|
||||
|
||||
private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
|
||||
{
|
||||
if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
|
||||
rigidBody.Velocity = information.Left.Transform.Position.FromTo(information.Right.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
|
||||
else
|
||||
rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
|
||||
|
||||
soundEffect.Play();
|
||||
|
||||
SendBallData();
|
||||
}
|
||||
|
||||
private void SendBallData()
|
||||
{
|
||||
if (communicator is not INetworkServer server)
|
||||
return;
|
||||
|
||||
LiteNetLib.Utils.NetDataWriter dataWriter = communicator.GetMessageWriter(this);
|
||||
dataWriter.Put(rigidBody.Transform.Position);
|
||||
dataWriter.Put(rigidBody.Velocity);
|
||||
server.Manager.SendToAll(dataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
protected override void OnMessageReceived(NetPacketReader reader, NetPeer peer)
|
||||
{
|
||||
rigidBody.Transform.Position = reader.GetVector2D();
|
||||
rigidBody.Velocity = reader.GetVector2D();
|
||||
}
|
||||
|
||||
public BallBehaviour() { }
|
||||
public BallBehaviour(Vector2D startDirection, float speed)
|
||||
{
|
||||
StartDirection = Vector2D.Normalize(startDirection);
|
||||
Speed = speed;
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
using Syntriax.Engine.Input;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class CameraController : Behaviour
|
||||
public class CameraController : BehaviourOverride
|
||||
{
|
||||
private MonoGameCamera2DBehaviour cameraBehaviour = null!;
|
||||
private IButtonInputs<Keys> buttonInputs = null!;
|
||||
@ -14,9 +14,15 @@ public class CameraController : Behaviour
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
cameraBehaviour ??= BehaviourController.GetRequiredBehaviour<MonoGameCamera2DBehaviour>();
|
||||
buttonInputs = GameManager.FindRequiredBehaviour<IButtonInputs<Keys>>();
|
||||
if (BehaviourController.TryGetBehaviour(out MonoGameCamera2DBehaviour? foundCameraBehaviour))
|
||||
cameraBehaviour = foundCameraBehaviour;
|
||||
|
||||
cameraBehaviour ??= BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>();
|
||||
|
||||
if (BehaviourController.TryGetBehaviour(out IButtonInputs<Keys>? foundButtonInputs))
|
||||
buttonInputs = foundButtonInputs;
|
||||
|
||||
buttonInputs ??= BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
|
||||
buttonInputs.RegisterOnPress(Keys.F, SwitchToFullScreen);
|
||||
buttonInputs.RegisterOnPress(Keys.R, ResetCamera);
|
||||
}
|
||||
@ -24,21 +30,21 @@ public class CameraController : Behaviour
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (buttonInputs.IsPressed(Keys.U))
|
||||
cameraBehaviour.Zoom += GameManager.Time.DeltaTime * 5f;
|
||||
cameraBehaviour.Zoom += Time.Elapsed.Nanoseconds * 0.00025f;
|
||||
if (buttonInputs.IsPressed(Keys.J))
|
||||
cameraBehaviour.Zoom -= GameManager.Time.DeltaTime * 5f;
|
||||
cameraBehaviour.Zoom -= Time.Elapsed.Nanoseconds * 0.00025f;
|
||||
|
||||
|
||||
if (buttonInputs.IsPressed(Keys.NumPad8)) cameraBehaviour.Transform.LocalPosition += Vector2D.Up * GameManager.Time.DeltaTime * 500f;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad2)) cameraBehaviour.Transform.LocalPosition -= Vector2D.Up * GameManager.Time.DeltaTime * 500f;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad6)) cameraBehaviour.Transform.LocalPosition += Vector2D.Right * GameManager.Time.DeltaTime * 500f;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad4)) cameraBehaviour.Transform.LocalPosition -= Vector2D.Right * GameManager.Time.DeltaTime * 500f;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad8)) cameraBehaviour.BehaviourController.GameObject.Transform.Position += Vector2D.Up.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad2)) cameraBehaviour.BehaviourController.GameObject.Transform.Position -= Vector2D.Up.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad6)) cameraBehaviour.BehaviourController.GameObject.Transform.Position += Vector2D.Right.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
|
||||
if (buttonInputs.IsPressed(Keys.NumPad4)) cameraBehaviour.BehaviourController.GameObject.Transform.Position -= Vector2D.Right.Rotate(Transform.Rotation * Math.DegreeToRadian) * Time.DeltaTimeFrame;
|
||||
|
||||
|
||||
if (buttonInputs.IsPressed(Keys.Q))
|
||||
cameraBehaviour.Transform.Rotation += GameManager.Time.DeltaTime * 45f;
|
||||
cameraBehaviour.BehaviourController.GameObject.Transform.Rotation += Time.Elapsed.Nanoseconds * 0.0025f;
|
||||
if (buttonInputs.IsPressed(Keys.E))
|
||||
cameraBehaviour.Transform.Rotation -= GameManager.Time.DeltaTime * 45f;
|
||||
cameraBehaviour.BehaviourController.GameObject.Transform.Rotation -= Time.Elapsed.Nanoseconds * 0.0025f;
|
||||
}
|
||||
|
||||
private void SwitchToFullScreen(IButtonInputs<Keys> inputs, Keys keys)
|
||||
@ -62,7 +68,7 @@ public class CameraController : Behaviour
|
||||
private void ResetCamera(IButtonInputs<Keys> inputs, Keys keys)
|
||||
{
|
||||
cameraBehaviour.Zoom = defaultZoomLevel;
|
||||
cameraBehaviour.Transform.LocalPosition = Vector2D.Zero;
|
||||
cameraBehaviour.Transform.LocalRotation = 0f;
|
||||
Transform.Position = Vector2D.Zero;
|
||||
Transform.Rotation = 0f;
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@ using Microsoft.Xna.Framework;
|
||||
|
||||
using Apos.Shapes;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Physics2D.Primitives;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
@ -1,17 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
using Syntriax.Engine.Input;
|
||||
|
||||
namespace Pong.Platforms.Desktop;
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
public class KeyboardInputsBehaviour : BehaviourOverride, IButtonInputs<Keys>
|
||||
{
|
||||
private readonly Dictionary<Keys, IButtonInputs<Keys>.ButtonCallbackEventHandler> OnPressed = new(256);
|
||||
private readonly Dictionary<Keys, IButtonInputs<Keys>.ButtonCallbackEventHandler> OnReleased = new(256);
|
||||
private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>?> OnPressed = new(256);
|
||||
private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>?> OnReleased = new(256);
|
||||
|
||||
private int cachePressedCurrentlyCount = 0;
|
||||
private readonly Keys[] cachePressedCurrently = new Keys[256];
|
||||
@ -19,10 +18,7 @@ public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
private int cachePressedPreviouslyCount = 0;
|
||||
private readonly Keys[] cachePressedPreviously = new Keys[256];
|
||||
|
||||
public event IButtonInputs<Keys>.ButtonCallbackEventHandler? OnAnyButtonPressed = null;
|
||||
public event IButtonInputs<Keys>.ButtonCallbackEventHandler? OnAnyButtonReleased = null;
|
||||
|
||||
public void RegisterOnPress(Keys key, IButtonInputs<Keys>.ButtonCallbackEventHandler callback)
|
||||
public void RegisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnPressed.TryGetValue(key, out var action))
|
||||
{
|
||||
@ -33,13 +29,13 @@ public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
OnPressed.Add(key, callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnPress(Keys key, IButtonInputs<Keys>.ButtonCallbackEventHandler callback)
|
||||
public void UnregisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnPressed.TryGetValue(key, out var action))
|
||||
action -= callback;
|
||||
}
|
||||
|
||||
public void RegisterOnRelease(Keys key, IButtonInputs<Keys>.ButtonCallbackEventHandler callback)
|
||||
public void RegisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnReleased.TryGetValue(key, out var action))
|
||||
{
|
||||
@ -50,7 +46,7 @@ public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
OnReleased.Add(key, callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnRelease(Keys key, IButtonInputs<Keys>.ButtonCallbackEventHandler callback)
|
||||
public void UnregisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnReleased.TryGetValue(key, out var action))
|
||||
action -= callback;
|
||||
@ -72,8 +68,7 @@ public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
if (WasPressed(currentlyPressedKey))
|
||||
continue;
|
||||
|
||||
action.Invoke(this, currentlyPressedKey);
|
||||
OnAnyButtonPressed?.Invoke(this, currentlyPressedKey);
|
||||
action?.Invoke(this, currentlyPressedKey);
|
||||
}
|
||||
|
||||
for (int i = 0; i < cachePressedPreviouslyCount; i++)
|
||||
@ -86,8 +81,7 @@ public class KeyboardInputsBehaviour : Behaviour, IButtonInputs<Keys>
|
||||
if (IsPressed(previouslyPressedKey))
|
||||
continue;
|
||||
|
||||
action.Invoke(this, previouslyPressedKey);
|
||||
OnAnyButtonReleased?.Invoke(this, previouslyPressedKey);
|
||||
action?.Invoke(this, previouslyPressedKey);
|
||||
}
|
||||
|
||||
Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount);
|
@ -6,11 +6,11 @@ using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : Behaviour2D, ICamera2D
|
||||
public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : BehaviourOverride, ICamera2D
|
||||
{
|
||||
public event OnMatrixTransformChangedDelegate? OnMatrixTransformChanged = null;
|
||||
public event OnViewportChangedDelegate? OnViewportChanged = null;
|
||||
public event OnZoomChangedDelegate? OnZoomChanged = null;
|
||||
public System.Action<MonoGameCamera2DBehaviour>? OnMatrixTransformChanged { get; set; } = null;
|
||||
public System.Action<MonoGameCamera2DBehaviour>? OnViewportChanged { get; set; } = null;
|
||||
public System.Action<MonoGameCamera2DBehaviour>? OnZoomChanged { get; set; } = null;
|
||||
|
||||
private Matrix _matrixTransform = Matrix.Identity;
|
||||
|
||||
@ -72,6 +72,10 @@ public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : Behavio
|
||||
set => Transform.Rotation = value;
|
||||
}
|
||||
|
||||
System.Action<IAssignableTransform>? IAssignableTransform.OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; }
|
||||
ITransform IAssignableTransform.Transform => GameObject.Transform;
|
||||
bool IAssignableTransform.Assign(ITransform transform) => GameObject.Assign(transform);
|
||||
|
||||
// TODO This causes delay since OnPreDraw calls assuming this is called in in Update
|
||||
public Vector2D ScreenToWorldPosition(Vector2D screenPosition)
|
||||
{
|
||||
@ -95,8 +99,4 @@ public class MonoGameCamera2DBehaviour(GraphicsDeviceManager Graphics) : Behavio
|
||||
Matrix.CreateScale(Zoom) *
|
||||
Matrix.CreateTranslation(new Vector3(_viewport.Width * .5f, _viewport.Height * .5f, 0f));
|
||||
}
|
||||
|
||||
public delegate void OnMatrixTransformChangedDelegate(MonoGameCamera2DBehaviour sender);
|
||||
public delegate void OnViewportChangedDelegate(MonoGameCamera2DBehaviour sender);
|
||||
public delegate void OnZoomChangedDelegate(MonoGameCamera2DBehaviour sender);
|
||||
}
|
@ -6,7 +6,7 @@ using Syntriax.Engine.Physics2D.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class MovementBallBehaviour : Behaviour2D
|
||||
public class MovementBallBehaviour : BehaviourOverride
|
||||
{
|
||||
public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
|
||||
public float Speed { get; set; } = 500f;
|
||||
@ -16,10 +16,15 @@ public class MovementBallBehaviour : Behaviour2D
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
rigidBody = BehaviourController.GetRequiredBehaviour<IRigidBody2D>();
|
||||
if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? foundRigidBody))
|
||||
throw new Exception($"{nameof(IRigidBody2D)} is missing on {GameObject.Name}.");
|
||||
if (!BehaviourController.TryGetBehaviour(out ICollider2D? foundCollider))
|
||||
throw new Exception($"{nameof(ICollider2D)} is missing on {GameObject.Name}.");
|
||||
|
||||
rigidBody.Velocity = StartDirection * Speed;
|
||||
BehaviourController.GetRequiredBehaviour<ICollider2D>().OnCollisionDetected += OnCollisionDetected;
|
||||
foundRigidBody.Velocity = StartDirection * Speed;
|
||||
foundCollider.OnCollisionDetected += OnCollisionDetected;
|
||||
|
||||
rigidBody = foundRigidBody;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
@ -27,14 +32,14 @@ public class MovementBallBehaviour : Behaviour2D
|
||||
if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
|
||||
return;
|
||||
|
||||
Vector2D speedUp = rigidBody.Velocity.Normalized * GameManager.Time.DeltaTime;
|
||||
Vector2D speedUp = rigidBody.Velocity.Normalized * Time.DeltaTimeFrame;
|
||||
rigidBody.Velocity += speedUp * SpeedUpMultiplier;
|
||||
}
|
||||
|
||||
private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
|
||||
{
|
||||
if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
|
||||
rigidBody.Velocity = information.Detector.Transform.Position.FromTo(information.Detected.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
|
||||
rigidBody.Velocity = information.Left.Transform.Position.FromTo(information.Right.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
|
||||
else
|
||||
rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
|
||||
}
|
154
Game/Behaviours/NetworkedKeyboardInputs.cs
Normal file
154
Game/Behaviours/NetworkedKeyboardInputs.cs
Normal file
@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LiteNetLib;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Syntriax.Engine.Input;
|
||||
using Syntriax.Engine.Network;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class NetworkedKeyboardInputs : NetworkBehaviour, IButtonInputs<Keys>
|
||||
{
|
||||
private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>?> OnPressed = new(256);
|
||||
private readonly Dictionary<Keys, Action<IButtonInputs<Keys>, Keys>?> OnReleased = new(256);
|
||||
|
||||
private int cachePressedCurrentlyCount = 0;
|
||||
private readonly Keys[] cachePressedCurrently = new Keys[256];
|
||||
|
||||
private int cachePressedPreviouslyCount = 0;
|
||||
private readonly Keys[] cachePressedPreviously = new Keys[256];
|
||||
|
||||
public void RegisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnPressed.TryGetValue(key, out var action))
|
||||
{
|
||||
action += callback;
|
||||
OnPressed.Remove(key);
|
||||
OnPressed.Add(key, action);
|
||||
return;
|
||||
}
|
||||
|
||||
OnPressed.Add(key, callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnPress(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnPressed.TryGetValue(key, out var action))
|
||||
action -= callback;
|
||||
}
|
||||
|
||||
public void RegisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnReleased.TryGetValue(key, out var action))
|
||||
{
|
||||
action += callback;
|
||||
OnReleased.Remove(key);
|
||||
OnReleased.Add(key, action);
|
||||
return;
|
||||
}
|
||||
|
||||
OnReleased.Add(key, callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnRelease(Keys key, Action<IButtonInputs<Keys>, Keys> callback)
|
||||
{
|
||||
if (OnReleased.TryGetValue(key, out var action))
|
||||
action -= callback;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (!IsServer && !LocalAssigned)
|
||||
return;
|
||||
|
||||
KeyboardState keyboardState = Keyboard.GetState();
|
||||
keyboardState.GetPressedKeys(cachePressedCurrently);
|
||||
cachePressedCurrentlyCount = keyboardState.GetPressedKeyCount();
|
||||
|
||||
for (int i = 0; i < cachePressedCurrentlyCount; i++)
|
||||
{
|
||||
Keys currentlyPressedKey = cachePressedCurrently[i];
|
||||
|
||||
if (!OnPressed.TryGetValue(currentlyPressedKey, out var action))
|
||||
continue;
|
||||
|
||||
if (WasPressed(currentlyPressedKey))
|
||||
continue;
|
||||
|
||||
action?.Invoke(this, currentlyPressedKey);
|
||||
}
|
||||
|
||||
for (int i = 0; i < cachePressedPreviouslyCount; i++)
|
||||
{
|
||||
Keys previouslyPressedKey = cachePressedPreviously[i];
|
||||
|
||||
if (!OnReleased.TryGetValue(previouslyPressedKey, out var action))
|
||||
continue;
|
||||
|
||||
if (IsPressed(previouslyPressedKey))
|
||||
continue;
|
||||
|
||||
action?.Invoke(this, previouslyPressedKey);
|
||||
}
|
||||
|
||||
Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount);
|
||||
cachePressedPreviouslyCount = cachePressedCurrentlyCount;
|
||||
}
|
||||
|
||||
public bool IsPressed(Keys key)
|
||||
{
|
||||
for (int i = 0; i < cachePressedCurrentlyCount; i++)
|
||||
if (cachePressedCurrently[i] == key)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool WasPressed(Keys key)
|
||||
{
|
||||
for (int i = 0; i < cachePressedPreviouslyCount; i++)
|
||||
if (cachePressedPreviously[i] == key)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
base.OnInitialize();
|
||||
foreach (Keys key in Enum.GetValues(typeof(Keys)))
|
||||
{
|
||||
RegisterOnPress(key, (keys, keyVal) =>
|
||||
{
|
||||
if (!LocalAssigned && !IsServer)
|
||||
return;
|
||||
|
||||
var netDataWriter = NetworkCommunicator.GetMessageWriter(this);
|
||||
netDataWriter.Put(true);
|
||||
netDataWriter.Put((int)key);
|
||||
NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
});
|
||||
RegisterOnRelease(key, (keys, keyVal) =>
|
||||
{
|
||||
if (!LocalAssigned && !IsServer)
|
||||
return;
|
||||
|
||||
var netDataWriter = NetworkCommunicator.GetMessageWriter(this);
|
||||
netDataWriter.Put(false);
|
||||
netDataWriter.Put((int)key);
|
||||
NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMessageReceived(NetPacketReader reader, NetPeer peer)
|
||||
{
|
||||
bool isPressed = reader.GetBool();
|
||||
Keys key = (Keys)reader.GetInt();
|
||||
|
||||
if (isPressed)
|
||||
if (OnPressed.TryGetValue(key, out var action))
|
||||
action?.Invoke(this, key);
|
||||
if (!isPressed)
|
||||
if (OnReleased.TryGetValue(key, out var action))
|
||||
action?.Invoke(this, key);
|
||||
}
|
||||
}
|
101
Game/Behaviours/PaddleBehaviour.cs
Normal file
101
Game/Behaviours/PaddleBehaviour.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Input;
|
||||
using Syntriax.Engine.Network;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : BehaviourOverride
|
||||
{
|
||||
private Keys Up { get; } = Up;
|
||||
private Keys Down { get; } = Down;
|
||||
public float High { get; } = High;
|
||||
public float Low { get; } = Low;
|
||||
public float Speed { get; set; } = Speed;
|
||||
|
||||
private bool isUpPressed = false;
|
||||
private bool isDownPressed = false;
|
||||
|
||||
private IButtonInputs<Keys> inputs = null!;
|
||||
private INetworkCommunicator communicator = null!;
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (isUpPressed && isDownPressed)
|
||||
return;
|
||||
|
||||
if (isUpPressed)
|
||||
MovePaddle(Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed);
|
||||
else if (isDownPressed)
|
||||
MovePaddle(-Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed);
|
||||
}
|
||||
|
||||
private void MovePaddle(Vector2D vectorToAdd)
|
||||
{
|
||||
GameObject.Transform.Position += vectorToAdd;
|
||||
GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
|
||||
}
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
BehaviourController.TryGetBehaviour<IButtonInputs<Keys>>(out var behaviourResult);
|
||||
inputs = behaviourResult ?? throw new Exception($"{nameof(IButtonInputs<Keys>)} is missing on {GameObject.Name}.");
|
||||
|
||||
if (!GameObject.GameManager.TryFindBehaviour(out INetworkCommunicator? foundCommunicator))
|
||||
throw new Exception($"{nameof(INetworkCommunicator)} is missing on GameManager.");
|
||||
|
||||
inputs.RegisterOnPress(Up, OnUpPressed);
|
||||
inputs.RegisterOnRelease(Up, OnUpReleased);
|
||||
|
||||
inputs.RegisterOnPress(Down, OnDownPressed);
|
||||
inputs.RegisterOnRelease(Down, OnDownReleased);
|
||||
|
||||
communicator = foundCommunicator;
|
||||
communicator.RegisterEntityListener(this, OnDataReceived);
|
||||
}
|
||||
|
||||
protected override void OnFinalize()
|
||||
{
|
||||
inputs.UnregisterOnPress(Up, OnUpPressed);
|
||||
inputs.UnregisterOnRelease(Up, OnUpReleased);
|
||||
|
||||
inputs.UnregisterOnPress(Down, OnDownPressed);
|
||||
inputs.UnregisterOnRelease(Down, OnDownReleased);
|
||||
}
|
||||
|
||||
private void UpdateNetwork()
|
||||
{
|
||||
NetDataWriter netDataWriter = communicator.GetEntityWriter(this);
|
||||
netDataWriter.Put(isUpPressed);
|
||||
netDataWriter.Put(isDownPressed);
|
||||
netDataWriter.Put(Transform.Position);
|
||||
communicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
private void OnDataReceived(NetPacketReader reader, NetPeer peer)
|
||||
{
|
||||
if (communicator is INetworkServer server)
|
||||
{
|
||||
reader.Get(out isUpPressed);
|
||||
reader.Get(out isDownPressed);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Get(out isUpPressed);
|
||||
reader.Get(out isDownPressed);
|
||||
Transform.Position = reader.GetVector2D();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = true; UpdateNetwork(); }
|
||||
private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = false; UpdateNetwork(); }
|
||||
private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = true; UpdateNetwork(); }
|
||||
private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = false; UpdateNetwork(); }
|
||||
}
|
104
Game/Behaviours/PongManagerBehaviour.cs
Normal file
104
Game/Behaviours/PongManagerBehaviour.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using LiteNetLib;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Network;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class PongManagerBehaviour : NetworkBehaviour
|
||||
{
|
||||
public Action<PongManagerBehaviour>? OnReset { get; set; } = null;
|
||||
public Action<PongManagerBehaviour>? OnFinished { get; set; } = null;
|
||||
public Action<PongManagerBehaviour>? OnScoresUpdated { get; set; } = null;
|
||||
public Action<PongManagerBehaviour>? OnScored { get; set; } = null;
|
||||
|
||||
private INetworkCommunicator communicator = null!;
|
||||
|
||||
public int ScoreLeft { get; private set; } = 0;
|
||||
public int ScoreRight { get; private set; } = 0;
|
||||
public int ScoreSum => ScoreLeft + ScoreRight;
|
||||
|
||||
public int WinScore { get; } = 5;
|
||||
|
||||
public PongManagerBehaviour() => WinScore = 5;
|
||||
public PongManagerBehaviour(int winScore) => WinScore = winScore;
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
KeyboardInputsBehaviour? buttonInputs = null!;
|
||||
|
||||
if (!BehaviourController.TryGetBehaviour(out buttonInputs))
|
||||
buttonInputs = BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
|
||||
|
||||
if (!GameObject.GameManager.TryFindBehaviour(out INetworkCommunicator? foundCommunicator))
|
||||
throw new Exception($"{nameof(INetworkCommunicator)} is missing on GameManager.");
|
||||
|
||||
buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => Reset());
|
||||
|
||||
communicator = foundCommunicator;
|
||||
}
|
||||
|
||||
public void ScoreToLeft()
|
||||
{
|
||||
ScoreLeft++;
|
||||
OnScoresUpdated?.Invoke(this);
|
||||
OnScored?.Invoke(this);
|
||||
|
||||
SendData();
|
||||
|
||||
CheckFinish();
|
||||
}
|
||||
|
||||
public void ScoreToRight()
|
||||
{
|
||||
ScoreRight++;
|
||||
OnScoresUpdated?.Invoke(this);
|
||||
OnScored?.Invoke(this);
|
||||
|
||||
SendData();
|
||||
|
||||
CheckFinish();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ScoreLeft = ScoreRight = 0;
|
||||
OnScoresUpdated?.Invoke(this);
|
||||
OnReset?.Invoke(this);
|
||||
|
||||
SendData();
|
||||
}
|
||||
|
||||
private void CheckFinish()
|
||||
{
|
||||
int halfwayScore = (int)(WinScore * .5f);
|
||||
|
||||
if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
|
||||
OnFinished?.Invoke(this);
|
||||
}
|
||||
|
||||
private void SendData()
|
||||
{
|
||||
if (communicator is not INetworkServer server)
|
||||
return;
|
||||
|
||||
LiteNetLib.Utils.NetDataWriter dataWriter = communicator.GetMessageWriter(this);
|
||||
dataWriter.Put(ScoreLeft);
|
||||
dataWriter.Put(ScoreRight);
|
||||
server.Manager.SendToAll(dataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
protected override void OnMessageReceived(NetPacketReader reader, NetPeer peer)
|
||||
{
|
||||
ScoreLeft = reader.GetInt();
|
||||
ScoreRight = reader.GetInt();
|
||||
OnScoresUpdated?.Invoke(this);
|
||||
|
||||
CheckFinish();
|
||||
}
|
||||
}
|
@ -4,12 +4,13 @@ using Apos.Shapes;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Input;
|
||||
using Syntriax.Engine.Physics2D.Abstract;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
using Syntriax.Engine.Physics2D.Primitives;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class ShapeAABBBehaviour : Behaviour2D, IDisplayableShape
|
||||
public class ShapeAABBBehaviour : BehaviourOverride, IDisplayableShape
|
||||
{
|
||||
private IShapeCollider2D? shapeCollider = null;
|
||||
|
@ -2,8 +2,8 @@ using Microsoft.Xna.Framework;
|
||||
|
||||
using Apos.Shapes;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Physics2D.Primitives;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
@ -26,8 +26,8 @@ public class ShapeBehaviour : Syntriax.Engine.Physics2D.Collider2DShapeBehaviour
|
||||
shapeBatch.DrawLine(ShapeWorld[0].ToDisplayVector2(), ShapeWorld[^1].ToDisplayVector2(), Thickness, Color, Color);
|
||||
}
|
||||
|
||||
public ShapeBehaviour(Shape2D shape) : base(shape) { }
|
||||
public ShapeBehaviour(Shape2D shape, float thickness) : base(shape) { Thickness = thickness; }
|
||||
public ShapeBehaviour(Shape2D shape, Color color) : base(shape) { Color = color; }
|
||||
public ShapeBehaviour(Shape2D shape, Color color, float thickness) : base(shape) { Thickness = thickness; Color = color; }
|
||||
public ShapeBehaviour(Shape shape) : base(shape) { }
|
||||
public ShapeBehaviour(Shape shape, float thickness) : base(shape) { Thickness = thickness; }
|
||||
public ShapeBehaviour(Shape shape, Color color) : base(shape) { Color = color; }
|
||||
public ShapeBehaviour(Shape shape, Color color, float thickness) : base(shape) { Thickness = thickness; Color = color; }
|
||||
}
|
@ -6,7 +6,7 @@ using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class TextBehaviour : Behaviour2D, IDisplayableSprite
|
||||
public class TextBehaviour : BehaviourOverride, IDisplayableSprite
|
||||
{
|
||||
public SpriteFont? Font { get; set; } = null;
|
||||
public int Size { get; set; } = 16;
|
@ -11,11 +11,10 @@ public class TextScoreBehaviour : TextBehaviour
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
if (!HierarchyObject.GameManager.TryFindBehaviour(out pongManager))
|
||||
if (!GameObject.GameManager.TryFindBehaviour(out pongManager))
|
||||
return;
|
||||
|
||||
pongManager.OnScored += UpdateScores;
|
||||
pongManager.OnReset += UpdateScores;
|
||||
pongManager.OnScoresUpdated += UpdateScores;
|
||||
|
||||
UpdateScores(pongManager);
|
||||
}
|
@ -5,7 +5,7 @@ using Syntriax.Engine.Physics2D.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class WallScoreBehaviour(Action OnCollision) : Behaviour2D
|
||||
public class WallScoreBehaviour(Action OnCollision) : BehaviourOverride
|
||||
{
|
||||
private Action OnCollision { get; } = OnCollision;
|
||||
|
@ -13,6 +13,12 @@
|
||||
|
||||
#---------------------------------- Content ---------------------------------#
|
||||
|
||||
#begin Hit.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Hit.wav
|
||||
|
||||
#begin UbuntuMono.spritefont
|
||||
/importer:FontDescriptionImporter
|
||||
/processor:FontDescriptionProcessor
|
BIN
Game/Content/Hit.wav
Normal file
BIN
Game/Content/Hit.wav
Normal file
Binary file not shown.
@ -6,7 +6,6 @@
|
||||
<PublishReadyToRun>false</PublishReadyToRun>
|
||||
<TieredCompilation>false</TieredCompilation>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>Pong.Platforms.Desktop</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
@ -17,28 +16,19 @@
|
||||
<None Remove="Icon.bmp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Icon.ico">
|
||||
<LogicalName>Icon.ico</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Icon.bmp">
|
||||
<LogicalName>Icon.bmp</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Icon.ico" />
|
||||
<EmbeddedResource Include="Icon.bmp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105" />
|
||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.2.1105" />
|
||||
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
||||
<PackageReference Include="LiteNetLib" Version="1.2.0" />
|
||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../Shared/Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MonoGameContentReference Include="../../Shared/Content/Content.mgcb">
|
||||
<Link>Content/Content.mgcb</Link>
|
||||
</MonoGameContentReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../Shared/Shared.csproj" />
|
||||
<ProjectReference Include="..\Engine\Engine.Core\Engine.Core.csproj" />
|
||||
<ProjectReference Include="..\Engine\Engine.Input\Engine.Input.csproj" />
|
||||
<ProjectReference Include="..\Engine\Engine.Physics2D\Engine.Physics2D.csproj" />
|
||||
</ItemGroup>
|
||||
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
|
||||
<Message Text="Restoring dotnet tools" Importance="High" />
|
200
Game/GamePong.cs
Normal file
200
Game/GamePong.cs
Normal file
@ -0,0 +1,200 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Apos.Shapes;
|
||||
|
||||
using Pong.Behaviours;
|
||||
using Syntriax.Engine.Network;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Physics2D;
|
||||
using Syntriax.Engine.Physics2D.Abstract;
|
||||
using Syntriax.Engine.Physics2D.Primitives;
|
||||
|
||||
namespace Pong;
|
||||
|
||||
public class GamePong : Game
|
||||
{
|
||||
private readonly GraphicsDeviceManager graphics = null!;
|
||||
private IPhysicsEngine2D physicsEngine = null!;
|
||||
private SpriteBatch spriteBatch = null!;
|
||||
private ShapeBatch shapeBatch = null!;
|
||||
|
||||
private GameManager gameManager = null!;
|
||||
private BehaviourCollector<IDisplayableSprite> displayableCollector = null!;
|
||||
private BehaviourCollector<IDisplayableShape> displayableShapeCollector = null!;
|
||||
private BehaviourCollector<IMonoGameContentLoader> monoGameContentLoaderCollector = null!;
|
||||
private MonoGameCamera2DBehaviour cameraBehaviour = null!;
|
||||
|
||||
private PongManagerBehaviour pongManager = null!;
|
||||
|
||||
private float physicsTimer = 0f;
|
||||
|
||||
public GamePong()
|
||||
{
|
||||
graphics = new GraphicsDeviceManager(this)
|
||||
{
|
||||
PreferredBackBufferWidth = 1024,
|
||||
PreferredBackBufferHeight = 576,
|
||||
GraphicsProfile = GraphicsProfile.HiDef
|
||||
};
|
||||
|
||||
Content.RootDirectory = "Content";
|
||||
IsMouseVisible = true;
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
// TODO: Add your initialization logic here
|
||||
gameManager = new();
|
||||
displayableCollector = new(gameManager);
|
||||
displayableShapeCollector = new(gameManager);
|
||||
monoGameContentLoaderCollector = new(gameManager);
|
||||
physicsEngine = new PhysicsEngine2DCollector(gameManager) { IterationPerStep = 3 };
|
||||
|
||||
monoGameContentLoaderCollector.OnCollected += (_, cached) => cached.LoadContent(Content);
|
||||
|
||||
gameManager.Initialize();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
protected override void LoadContent()
|
||||
{
|
||||
spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
shapeBatch = new ShapeBatch(GraphicsDevice, Content);
|
||||
SpriteFont spriteFont = Content.Load<SpriteFont>("UbuntuMono");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string[] commandLineArguments = Environment.GetCommandLineArgs();
|
||||
if (commandLineArguments.Length != 1)
|
||||
{
|
||||
if (commandLineArguments[1].Equals("server", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkServer>().Start(8888, 2);
|
||||
Window.Title = "Pong - Server";
|
||||
}
|
||||
else
|
||||
{
|
||||
Window.Title = $"Pong - Client -> {commandLineArguments[1]}";
|
||||
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect(commandLineArguments[1], 8888);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gameManager.InstantiateGameObject().BehaviourController.AddBehaviour<NetworkClient>().Connect("127.0.0.1", 8888);
|
||||
Window.Title = $"Pong - Client -> 127.0.0.1";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectCamera = gameManager.InstantiateGameObject().SetGameObject("Camera"); ;
|
||||
gameObjectCamera.BehaviourController.AddBehaviour<CameraController>();
|
||||
cameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>(graphics);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectPongManager = gameManager.InstantiateGameObject().SetGameObject("Pong Game Manager");
|
||||
pongManager = gameObjectPongManager.BehaviourController.AddBehaviour<PongManagerBehaviour>(5);
|
||||
pongManager.Id = "pongManager";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectBall = gameManager.InstantiateGameObject().SetGameObject("Ball");
|
||||
gameObjectBall.Transform.SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f));
|
||||
|
||||
gameObjectBall.BehaviourController.AddBehaviour<CircleBehaviour>(new Circle(Vector2D.Zero, 1f));
|
||||
gameObjectBall.BehaviourController.AddBehaviour<BallBehaviour>().Id = "ball";
|
||||
gameObjectBall.BehaviourController.AddBehaviour<RigidBody2D>();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectLeftPaddle = gameManager.InstantiateGameObject().SetGameObject("Left Paddle");
|
||||
gameObjectLeftPaddle.Transform.SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f));
|
||||
|
||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<NetworkedKeyboardInputs>().Id = "leftPaddleInput";
|
||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.W, Keys.S, 228f, -228f, 400f).Id = "leftPaddle";
|
||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectLeftPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IGameObject gameObjectRightPaddle = gameManager.InstantiateGameObject().SetGameObject("Right Paddle");
|
||||
gameObjectRightPaddle.Transform.SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f));
|
||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<NetworkedKeyboardInputs>().Id = "rightPaddleInput";
|
||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.Up, Keys.Down, 228f, -228f, 400f).Id = "rightPaddle";
|
||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectRightPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectWallTop = gameManager.InstantiateGameObject().SetGameObject("Wall Top");
|
||||
gameObjectWallTop.Transform.SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f));
|
||||
gameObjectWallTop.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectWallTop.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IGameObject gameObjectWallBottom = gameManager.InstantiateGameObject().SetGameObject("Wall Bottom");
|
||||
gameObjectWallBottom.Transform.SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f));
|
||||
gameObjectWallBottom.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectWallBottom.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IGameObject gameObjectWallRight = gameManager.InstantiateGameObject().SetGameObject("Wall Right");
|
||||
gameObjectWallRight.Transform.SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f));
|
||||
gameObjectWallRight.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToLeft);
|
||||
gameObjectWallRight.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectWallRight.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IGameObject gameObjectWallLeft = gameManager.InstantiateGameObject().SetGameObject("Wall Left");
|
||||
gameObjectWallLeft.Transform.SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f));
|
||||
gameObjectWallLeft.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToRight);
|
||||
gameObjectWallLeft.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape.Box);
|
||||
gameObjectWallLeft.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IGameObject gameObjectLeftScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Left");
|
||||
gameObjectLeftScoreText.Transform.SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f);
|
||||
gameObjectLeftScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(true, spriteFont);
|
||||
|
||||
IGameObject gameObjectRightScoreText = gameManager.InstantiateGameObject().SetGameObject("Score Right");
|
||||
gameObjectRightScoreText.Transform.SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f);
|
||||
gameObjectRightScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(false, spriteFont);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||
Exit();
|
||||
|
||||
gameManager.Update(gameTime.ToEngineTime());
|
||||
while (physicsTimer + 0.01f < gameTime.TotalGameTime.TotalMilliseconds * .001f)//seconds)
|
||||
{
|
||||
physicsTimer += 0.01f;
|
||||
physicsEngine.Step(.01f);
|
||||
}
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
protected override void Draw(GameTime gameTime)
|
||||
{
|
||||
GraphicsDevice.Clear(new Color() { R = 32, G = 32, B = 32 });
|
||||
|
||||
// TODO: Add your drawing code here
|
||||
gameManager.PreDraw();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cameraBehaviour.MatrixTransform);
|
||||
foreach (var displayable in displayableCollector)
|
||||
displayable.Draw(spriteBatch);
|
||||
spriteBatch.End();
|
||||
|
||||
shapeBatch.Begin(cameraBehaviour.MatrixTransform);
|
||||
foreach (var displayableShape in displayableShapeCollector)
|
||||
displayableShape.Draw(shapeBatch);
|
||||
shapeBatch.End();
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 256 KiB |
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
18
Game/Network/Abstract/INetworkBehaviour.cs
Normal file
18
Game/Network/Abstract/INetworkBehaviour.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkBehaviour : IBehaviour
|
||||
{
|
||||
int NetworkId { get; }
|
||||
|
||||
bool LocalAssigned { get; }
|
||||
|
||||
bool IsServer { get; }
|
||||
bool IsClient { get; }
|
||||
|
||||
INetworkCommunicator NetworkCommunicator { get; }
|
||||
|
||||
public void RequestAssignment();
|
||||
public void ReleaseAssignment();
|
||||
}
|
6
Game/Network/Abstract/INetworkClient.cs
Normal file
6
Game/Network/Abstract/INetworkClient.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkClient : INetworkCommunicator
|
||||
{
|
||||
void Connect(string address, int port, string? password = null);
|
||||
}
|
22
Game/Network/Abstract/INetworkCommunicator.cs
Normal file
22
Game/Network/Abstract/INetworkCommunicator.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkCommunicator
|
||||
{
|
||||
EventBasedNetListener Listener { get; }
|
||||
NetManager Manager { get; }
|
||||
|
||||
void PollEvents();
|
||||
void Stop();
|
||||
|
||||
void RegisterEntityListener(IEntity entity, Action<NetPacketReader, NetPeer> onDataReceived);
|
||||
void UnregisterEntityListener(IEntity entity);
|
||||
NetDataWriter GetEntityWriter(IEntity entity);
|
||||
NetDataWriter GetMessageWriter(IEntity entity);
|
||||
}
|
11
Game/Network/Abstract/INetworkEntity.cs
Normal file
11
Game/Network/Abstract/INetworkEntity.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
internal interface INetworkEntity
|
||||
{
|
||||
Action<INetworkEntity, int> OnNetworkIdChanged { get; set; }
|
||||
int NetworkId { get; set; }
|
||||
|
||||
void SetNetworkId(int id);
|
||||
}
|
10
Game/Network/Abstract/INetworkManager.cs
Normal file
10
Game/Network/Abstract/INetworkManager.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkManager
|
||||
{
|
||||
// Action<IGameObject>? OnNetworkGameObjectInstantiated { get; set; }
|
||||
|
||||
INetworkCommunicator NetworkCommunicator { get; }
|
||||
|
||||
// Task<T> Instantiate<T>(params object?[]? args) where T : class, IGameObject;
|
||||
}
|
10
Game/Network/Abstract/INetworkServer.cs
Normal file
10
Game/Network/Abstract/INetworkServer.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkServer : INetworkCommunicator
|
||||
{
|
||||
string Password { get; }
|
||||
int MaxConnectionCount { get; }
|
||||
int Port { get; }
|
||||
|
||||
void Start(int port, int maxConnectionCount, string? password = null);
|
||||
}
|
81
Game/Network/NetworkBase.cs
Normal file
81
Game/Network/NetworkBase.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator
|
||||
{
|
||||
public EventBasedNetListener Listener { get; private set; } = null!;
|
||||
public NetManager Manager { get; private set; } = null!;
|
||||
|
||||
public NetworkBase()
|
||||
{
|
||||
Priority = 10;
|
||||
|
||||
Listener = new EventBasedNetListener();
|
||||
Manager = new NetManager(Listener);
|
||||
|
||||
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
||||
}
|
||||
|
||||
public void PollEvents() => Manager.PollEvents();
|
||||
public void Stop() => Manager.Stop();
|
||||
|
||||
protected override void OnUpdate() => PollEvents();
|
||||
protected override void OnFinalize() => Stop();
|
||||
|
||||
private readonly Dictionary<string, Action<NetPacketReader, NetPeer>> callbacks = new(32);
|
||||
|
||||
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (callbacks.TryGetValue(reader.GetString(), out var action))
|
||||
action?.Invoke(reader, peer);
|
||||
|
||||
reader.Recycle();
|
||||
}
|
||||
|
||||
public void RegisterEntityListener(IEntity entity, Action<NetPacketReader, NetPeer> onDataReceived)
|
||||
{
|
||||
if (callbacks.ContainsKey(entity.Id))
|
||||
return;
|
||||
|
||||
callbacks.Add(entity.Id, onDataReceived);
|
||||
entity.OnIdChanged += OnEntityIdChanged;
|
||||
}
|
||||
|
||||
public void UnregisterEntityListener(IEntity entity)
|
||||
{
|
||||
if (!callbacks.Remove(entity.Id))
|
||||
return;
|
||||
|
||||
entity.OnIdChanged -= OnEntityIdChanged;
|
||||
}
|
||||
|
||||
public NetDataWriter GetMessageWriter(IEntity entity)
|
||||
{
|
||||
NetDataWriter netDataWriter = GetEntityWriter(entity);
|
||||
netDataWriter.Put((int)MessageType.Message);
|
||||
return netDataWriter;
|
||||
}
|
||||
|
||||
public NetDataWriter GetEntityWriter(IEntity entity)
|
||||
{
|
||||
NetDataWriter netDataWriter = new();
|
||||
netDataWriter.Put(entity.Id);
|
||||
return netDataWriter;
|
||||
}
|
||||
|
||||
private void OnEntityIdChanged(IEntity entity, string previousId)
|
||||
{
|
||||
var action = callbacks[previousId];
|
||||
callbacks.Remove(previousId);
|
||||
callbacks.Add(entity.Id, action);
|
||||
}
|
||||
}
|
99
Game/Network/NetworkBehaviour.cs
Normal file
99
Game/Network/NetworkBehaviour.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using System;
|
||||
|
||||
using LiteNetLib;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public abstract class NetworkBehaviour : BehaviourOverride, INetworkBehaviour
|
||||
{
|
||||
public int NetworkId { get; private set; } = 0;
|
||||
|
||||
public bool LocalAssigned { get; private set; } = false;
|
||||
|
||||
public bool IsServer { get; private set; } = false;
|
||||
public bool IsClient { get; private set; } = false;
|
||||
|
||||
public INetworkCommunicator NetworkCommunicator { get; private set; } = null!;
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
NetworkCommunicator = BehaviourController.GetBehaviourInParent<INetworkCommunicator>()
|
||||
?? GameObject.GameManager.FindBehaviour<INetworkCommunicator>()
|
||||
?? throw new Exception($"Could not find an {nameof(INetworkCommunicator)}.");
|
||||
|
||||
NetworkCommunicator.RegisterEntityListener(this, OnMessageReceivedInternal);
|
||||
|
||||
if (NetworkCommunicator is INetworkClient client)
|
||||
{
|
||||
IsClient = true;
|
||||
return;
|
||||
}
|
||||
|
||||
IsServer = true;
|
||||
LocalAssigned = true;
|
||||
}
|
||||
|
||||
public void ReleaseAssignment()
|
||||
{
|
||||
if (IsServer)
|
||||
return;
|
||||
|
||||
var netDataWriter = NetworkCommunicator.GetEntityWriter(this);
|
||||
netDataWriter.Put((int)MessageType.AssignmentRelease);
|
||||
NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
public void RequestAssignment()
|
||||
{
|
||||
if (IsServer)
|
||||
return;
|
||||
|
||||
var netDataWriter = NetworkCommunicator.GetEntityWriter(this);
|
||||
netDataWriter.Put((int)MessageType.AssignmentRequest);
|
||||
NetworkCommunicator.Manager.SendToAll(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
protected abstract void OnMessageReceived(NetPacketReader reader, NetPeer peer);
|
||||
private void OnMessageReceivedInternal(NetPacketReader reader, NetPeer peer)
|
||||
{
|
||||
MessageType messageType = (MessageType)reader.GetInt();
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
switch (messageType)
|
||||
{
|
||||
case MessageType.Message: OnMessageReceived(reader, peer); break;
|
||||
case MessageType.AssignmentRequest:
|
||||
case MessageType.AssignmentRelease:
|
||||
var netDataWriter = NetworkCommunicator.GetEntityWriter(this);
|
||||
netDataWriter.Put((int)(messageType == MessageType.AssignmentRequest ? MessageType.Assigned : MessageType.Unassigned));
|
||||
peer.Send(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case MessageType.Message: OnMessageReceived(reader, peer); break;
|
||||
case MessageType.Assigned: LocalAssigned = true; break;
|
||||
case MessageType.Unassigned: LocalAssigned = false; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal enum MessageType
|
||||
{
|
||||
Message,
|
||||
AssignmentRequest,
|
||||
AssignmentRelease,
|
||||
Assigned,
|
||||
Unassigned,
|
||||
}
|
12
Game/Network/NetworkClient.cs
Normal file
12
Game/Network/NetworkClient.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkClient : NetworkBase, INetworkClient
|
||||
{
|
||||
public void Connect(string address, int port, string? password = null)
|
||||
{
|
||||
Manager.Start();
|
||||
Manager.Connect(address, port, password ?? string.Empty);
|
||||
}
|
||||
}
|
20
Game/Network/NetworkExtensions.cs
Normal file
20
Game/Network/NetworkExtensions.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public static class NetworkExtensions
|
||||
{
|
||||
public static Vector2D GetVector2D(this NetPacketReader reader)
|
||||
=> new(reader.GetFloat(), reader.GetFloat());
|
||||
public static void GetVector2D(this NetPacketReader reader, out Vector2D vector2D)
|
||||
=> vector2D = new(reader.GetFloat(), reader.GetFloat());
|
||||
|
||||
public static void Put(this NetDataWriter writer, Vector2D vector)
|
||||
{
|
||||
writer.Put(vector.X);
|
||||
writer.Put(vector.Y);
|
||||
}
|
||||
}
|
31
Game/Network/NetworkManager.cs
Normal file
31
Game/Network/NetworkManager.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using LiteNetLib;
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkManager : NetworkBehaviour, INetworkManager
|
||||
{
|
||||
private BehaviourCollector<INetworkEntity> entities = null!;
|
||||
|
||||
private static int networkIdIndex = 0;
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
base.OnInitialize();
|
||||
|
||||
((INetworkEntity)this).SetNetworkId(networkIdIndex++);
|
||||
|
||||
entities = new(GameObject.GameManager);
|
||||
foreach (var entity in entities)
|
||||
entity.SetNetworkId(networkIdIndex++);
|
||||
|
||||
entities.OnCollected += OnCollected;
|
||||
}
|
||||
|
||||
private void OnCollected(BehaviourCollector<INetworkEntity> collector, INetworkEntity entity)
|
||||
=> entity.SetNetworkId(networkIdIndex++);
|
||||
|
||||
protected override void OnMessageReceived(NetPacketReader reader, NetPeer peer) { }
|
||||
}
|
30
Game/Network/NetworkServer.cs
Normal file
30
Game/Network/NetworkServer.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkServer : NetworkBase, INetworkServer
|
||||
{
|
||||
public string Password { get; private set; } = string.Empty;
|
||||
public int MaxConnectionCount { get; private set; } = 0;
|
||||
public int Port { get; private set; } = 8888;
|
||||
|
||||
public NetworkServer() : base()
|
||||
{
|
||||
Listener.ConnectionRequestEvent += request =>
|
||||
{
|
||||
if (Manager.ConnectedPeersCount < MaxConnectionCount)
|
||||
request.AcceptIfKey(Password);
|
||||
else
|
||||
request.Reject();
|
||||
};
|
||||
}
|
||||
|
||||
public void Start(int port, int maxConnectionCount, string? password = null)
|
||||
{
|
||||
Password = password ?? string.Empty;
|
||||
MaxConnectionCount = maxConnectionCount;
|
||||
Port = port;
|
||||
|
||||
Manager.Start(port);
|
||||
}
|
||||
}
|
3
Game/Program.cs
Normal file
3
Game/Program.cs
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
using var game = new Pong.GamePong();
|
||||
game.Run();
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="Desktop"/>
|
||||
<assemblyIdentity version="1.0.0.0" name="Game"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
@ -1,15 +0,0 @@
|
||||
|
||||
#----------------------------- Global Properties ----------------------------#
|
||||
|
||||
/outputDir:bin/$(Platform)
|
||||
/intermediateDir:obj/$(Platform)
|
||||
/platform:DesktopGL
|
||||
/config:
|
||||
/profile:Reach
|
||||
/compress:False
|
||||
|
||||
#-------------------------------- References --------------------------------#
|
||||
|
||||
|
||||
#---------------------------------- Content ---------------------------------#
|
||||
|
@ -1,7 +0,0 @@
|
||||
using Pong.Platforms.Desktop;
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
Syntriax.Engine.Core.Abstract.IHierarchyObject hierarchyObject = Syntriax.Engine.Core.Factory.HierarchyObjectFactory.Instantiate().SetHierarchyObject("Desktop HO");
|
||||
hierarchyObject.BehaviourController.AddBehaviour<KeyboardInputsBehaviour>();
|
||||
using var game = new Pong.GamePong(hierarchyObject);
|
||||
game.Run();
|
48
Pong.sln
48
Pong.sln
@ -7,57 +7,41 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{F7F626
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Core", "Engine\Engine.Core\Engine.Core.csproj", "{990CA10C-1EBB-4395-A43A-456B7029D8C9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Game", "Game\Game.csproj", "{500E1B05-39D7-4232-8051-E7351D745306}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Input", "Engine\Engine.Input\Engine.Input.csproj", "{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Physics2D", "Engine\Engine.Physics2D\Engine.Physics2D.csproj", "{0D97F83C-B043-48B1-B155-7354C4E84FC0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine", "Engine\Engine\Engine.csproj", "{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{FECFFD54-338F-4060-9161-1E5770D1DC33}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Desktop", "Platforms\Desktop\Desktop.csproj", "{2B627F66-5A61-4F69-B479-62EEAB603D01}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Engine.Systems", "Engine\Engine.Systems\Engine.Systems.csproj", "{8863A1BA-2E83-419F-BACB-D4A4156EC71C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{990CA10C-1EBB-4395-A43A-456B7029D8C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{500E1B05-39D7-4232-8051-E7351D745306}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{500E1B05-39D7-4232-8051-E7351D745306}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{500E1B05-39D7-4232-8051-E7351D745306}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{500E1B05-39D7-4232-8051-E7351D745306}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0D97F83C-B043-48B1-B155-7354C4E84FC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F6B1E26-1217-4EFD-874C-05ADEE4C7969}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{590E392E-9FB3-49FA-B4DA-6C8F7126FFE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2B627F66-5A61-4F69-B479-62EEAB603D01}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2B627F66-5A61-4F69-B479-62EEAB603D01}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8863A1BA-2E83-419F-BACB-D4A4156EC71C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{990CA10C-1EBB-4395-A43A-456B7029D8C9} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
|
||||
{7EED4EC3-79D5-4C6C-A54D-1B396213C0E4} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
|
||||
{0D97F83C-B043-48B1-B155-7354C4E84FC0} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
|
||||
{2F6B1E26-1217-4EFD-874C-05ADEE4C7969} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
|
||||
{2B627F66-5A61-4F69-B479-62EEAB603D01} = {FECFFD54-338F-4060-9161-1E5770D1DC33}
|
||||
{8863A1BA-2E83-419F-BACB-D4A4156EC71C} = {F7F62670-237A-4C93-A30E-CE661C6FC401}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,36 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-mgcb": {
|
||||
"version": "3.8.2.1105",
|
||||
"commands": [
|
||||
"mgcb"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor": {
|
||||
"version": "3.8.2.1105",
|
||||
"commands": [
|
||||
"mgcb-editor"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-linux": {
|
||||
"version": "3.8.2.1105",
|
||||
"commands": [
|
||||
"mgcb-editor-linux"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-windows": {
|
||||
"version": "3.8.2.1105",
|
||||
"commands": [
|
||||
"mgcb-editor-windows"
|
||||
]
|
||||
},
|
||||
"dotnet-mgcb-editor-mac": {
|
||||
"version": "3.8.2.1105",
|
||||
"commands": [
|
||||
"mgcb-editor-mac"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Physics2D;
|
||||
using Syntriax.Engine.Physics2D.Abstract;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class BallBehaviour : Behaviour2D
|
||||
{
|
||||
public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
|
||||
public float Speed { get; set; } = 500f;
|
||||
public float SpeedUpMultiplier { get; set; } = .0125f;
|
||||
|
||||
private readonly Random random = new();
|
||||
private IRigidBody2D rigidBody = null!;
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
BehaviourController.GetRequiredBehaviour<ICollider2D>().OnCollisionDetected += OnCollisionDetected;
|
||||
rigidBody = BehaviourController.GetRequiredBehaviour<IRigidBody2D>();
|
||||
|
||||
if (HierarchyObject.GameManager.TryFindBehaviour(out PongManagerBehaviour? pongManager))
|
||||
{
|
||||
pongManager.OnReset += ResetBall;
|
||||
pongManager.OnScored += ResetBall;
|
||||
pongManager.OnFinished += DisableBall;
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableBall(PongManagerBehaviour pongManager)
|
||||
{
|
||||
Transform.Position = Vector2D.Zero;
|
||||
rigidBody.Velocity = Vector2D.Zero;
|
||||
}
|
||||
|
||||
private void ResetBall(PongManagerBehaviour pongManager)
|
||||
{
|
||||
StateEnable.Enabled = true;
|
||||
Transform.Position = Vector2D.Zero;
|
||||
rigidBody.Velocity = GetRandomDirection() * Speed;
|
||||
}
|
||||
|
||||
private Vector2D GetRandomDirection()
|
||||
{
|
||||
const float AllowedRadians = 45f * Syntriax.Engine.Core.Math.DegreeToRadian;
|
||||
float rotation = (float)random.NextDouble() * 2f * AllowedRadians - AllowedRadians;
|
||||
bool isBackwards = (random.Next() % 2) == 1;
|
||||
return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation);
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
|
||||
return;
|
||||
|
||||
Vector2D speedUp = rigidBody.Velocity.Normalized * GameManager.Time.DeltaTime;
|
||||
rigidBody.Velocity += speedUp * SpeedUpMultiplier;
|
||||
}
|
||||
|
||||
private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
|
||||
{
|
||||
if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
|
||||
rigidBody.Velocity = information.Detected.Transform.Position.FromTo(information.Detector.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
|
||||
else
|
||||
rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
|
||||
}
|
||||
|
||||
public BallBehaviour() { }
|
||||
public BallBehaviour(Vector2D startDirection, float speed)
|
||||
{
|
||||
StartDirection = Vector2D.Normalize(startDirection);
|
||||
Speed = speed;
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : Behaviour2D
|
||||
{
|
||||
private Keys Up { get; } = Up;
|
||||
private Keys Down { get; } = Down;
|
||||
public float High { get; } = High;
|
||||
public float Low { get; } = Low;
|
||||
public float Speed { get; set; } = Speed;
|
||||
|
||||
private bool isUpPressed = false;
|
||||
private bool isDownPressed = false;
|
||||
|
||||
private IButtonInputs<Keys> inputs = null!;
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if (isUpPressed && isDownPressed)
|
||||
return;
|
||||
|
||||
if (isUpPressed)
|
||||
Transform.Position = Transform.Position + Vector2D.Up * GameManager.Time.DeltaTime * Speed;
|
||||
else if (isDownPressed)
|
||||
Transform.Position = Transform.Position + -Vector2D.Up * GameManager.Time.DeltaTime * Speed;
|
||||
|
||||
Transform.Position = new Vector2D(Transform.Position.X, MathF.Max(MathF.Min(Transform.Position.Y, High), Low));
|
||||
}
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
inputs = GameManager.FindRequiredBehaviour<IButtonInputs<Keys>>();
|
||||
|
||||
inputs.RegisterOnPress(Up, OnUpPressed);
|
||||
inputs.RegisterOnRelease(Up, OnUpReleased);
|
||||
|
||||
inputs.RegisterOnPress(Down, OnDownPressed);
|
||||
inputs.RegisterOnRelease(Down, OnDownReleased);
|
||||
}
|
||||
|
||||
protected override void OnFinalize()
|
||||
{
|
||||
inputs.UnregisterOnPress(Up, OnUpPressed);
|
||||
inputs.UnregisterOnRelease(Up, OnUpReleased);
|
||||
|
||||
inputs.UnregisterOnPress(Down, OnDownPressed);
|
||||
inputs.UnregisterOnRelease(Down, OnDownReleased);
|
||||
}
|
||||
|
||||
private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = true;
|
||||
private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = false;
|
||||
private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = true;
|
||||
private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = false;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class PongManagerBehaviour : Behaviour
|
||||
{
|
||||
public Action<PongManagerBehaviour>? OnReset { get; set; } = null;
|
||||
public Action<PongManagerBehaviour>? OnFinished { get; set; } = null;
|
||||
public Action<PongManagerBehaviour>? OnScored { get; set; } = null;
|
||||
|
||||
public int ScoreLeft { get; private set; } = 0;
|
||||
public int ScoreRight { get; private set; } = 0;
|
||||
public int ScoreSum => ScoreLeft + ScoreRight;
|
||||
|
||||
public int WinScore { get; } = 5;
|
||||
|
||||
public PongManagerBehaviour() => WinScore = 5;
|
||||
public PongManagerBehaviour(int winScore) => WinScore = winScore;
|
||||
|
||||
protected override void OnFirstActiveFrame()
|
||||
{
|
||||
var buttonInputs = GameManager.FindRequiredBehaviour<IButtonInputs<Keys>>();
|
||||
buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => Reset());
|
||||
}
|
||||
|
||||
|
||||
public void ScoreToLeft()
|
||||
{
|
||||
ScoreLeft++;
|
||||
OnScored?.Invoke(this);
|
||||
|
||||
CheckFinish();
|
||||
}
|
||||
|
||||
public void ScoreToRight()
|
||||
{
|
||||
ScoreRight++;
|
||||
OnScored?.Invoke(this);
|
||||
|
||||
CheckFinish();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ScoreLeft = ScoreRight = 0;
|
||||
OnReset?.Invoke(this);
|
||||
}
|
||||
|
||||
private void CheckFinish()
|
||||
{
|
||||
int halfwayScore = (int)(WinScore * .5f);
|
||||
|
||||
if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
|
||||
OnFinished?.Invoke(this);
|
||||
}
|
||||
}
|
Binary file not shown.
@ -1,165 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Pong.Behaviours;
|
||||
using Apos.Shapes;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
using Syntriax.Engine.Physics2D;
|
||||
|
||||
namespace Pong;
|
||||
|
||||
public class GamePong : Game
|
||||
{
|
||||
private readonly IHierarchyObject platformSpecificHierarchyObject = null!;
|
||||
private readonly GraphicsDeviceManager graphics = null!;
|
||||
private SpriteBatch spriteBatch = null!;
|
||||
private ShapeBatch shapeBatch = null!;
|
||||
|
||||
private GameManager gameManager = null!;
|
||||
private BehaviourCollector<IDisplayableSprite> displayableCollector = null!;
|
||||
private BehaviourCollector<IDisplayableShape> displayableShapeCollector = null!;
|
||||
private MonoGameCamera2DBehaviour cameraBehaviour = null!;
|
||||
|
||||
private PongManagerBehaviour pongManager = null!;
|
||||
|
||||
public GamePong(IHierarchyObject platformSpecificHierarchyObject)
|
||||
{
|
||||
this.platformSpecificHierarchyObject = platformSpecificHierarchyObject;
|
||||
graphics = new GraphicsDeviceManager(this)
|
||||
{
|
||||
PreferredBackBufferWidth = 1024,
|
||||
PreferredBackBufferHeight = 576,
|
||||
GraphicsProfile = GraphicsProfile.HiDef
|
||||
};
|
||||
|
||||
Content.RootDirectory = "Content";
|
||||
IsMouseVisible = true;
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
// TODO: Add your initialization logic here
|
||||
gameManager = new();
|
||||
displayableCollector = new(gameManager);
|
||||
displayableShapeCollector = new(gameManager);
|
||||
|
||||
gameManager.Initialize();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
protected override void LoadContent()
|
||||
{
|
||||
spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
shapeBatch = new ShapeBatch(GraphicsDevice, Content);
|
||||
SpriteFont spriteFont = Content.Load<SpriteFont>("UbuntuMono");
|
||||
|
||||
gameManager.Register(platformSpecificHierarchyObject);
|
||||
gameManager.InstantiateHierarchyObject<PhysicsEngine2D>().SetHierarchyObject("Physics Engine 2D");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectCamera = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Camera"); ;
|
||||
HierarchyObjectCamera.BehaviourController.AddBehaviour<Transform2D>();
|
||||
|
||||
HierarchyObjectCamera.BehaviourController.AddBehaviour<CameraController>();
|
||||
cameraBehaviour = HierarchyObjectCamera.BehaviourController.AddBehaviour<MonoGameCamera2DBehaviour>(graphics);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectPongManager = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Pong Game Manager");
|
||||
pongManager = HierarchyObjectPongManager.BehaviourController.AddBehaviour<PongManagerBehaviour>(5);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectBall = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Ball");
|
||||
HierarchyObjectBall.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0, 0f), scale: new Vector2D(10f, 10f));
|
||||
|
||||
HierarchyObjectBall.BehaviourController.AddBehaviour<CircleBehaviour>(new Circle(Vector2D.Zero, 1f));
|
||||
HierarchyObjectBall.BehaviourController.AddBehaviour<BallBehaviour>();
|
||||
HierarchyObjectBall.BehaviourController.AddBehaviour<RigidBody2D>();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectLeftPaddle = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Left Paddle");
|
||||
HierarchyObjectLeftPaddle.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-468f, 0f), scale: new Vector2D(15f, 60f));
|
||||
|
||||
HierarchyObjectLeftPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.W, Keys.S, 228f, -228f, 400f);
|
||||
HierarchyObjectLeftPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectLeftPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IHierarchyObject HierarchyObjectRightPaddle = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Right Paddle");
|
||||
HierarchyObjectRightPaddle.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(468f, 0f), scale: new Vector2D(15f, 60f));
|
||||
HierarchyObjectRightPaddle.BehaviourController.AddBehaviour<PaddleBehaviour>(Keys.Up, Keys.Down, 228f, -228f, 400f);
|
||||
HierarchyObjectRightPaddle.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectRightPaddle.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectWallTop = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Wall Top");
|
||||
HierarchyObjectWallTop.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0f, 308f), scale: new Vector2D(552f, 20f));
|
||||
HierarchyObjectWallTop.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectWallTop.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IHierarchyObject HierarchyObjectWallBottom = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Wall Bottom");
|
||||
HierarchyObjectWallBottom.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(0f, -308f), scale: new Vector2D(552f, 20f));
|
||||
HierarchyObjectWallBottom.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectWallBottom.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IHierarchyObject HierarchyObjectWallRight = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Wall Right");
|
||||
HierarchyObjectWallRight.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(532f, 0f), scale: new Vector2D(20f, 328f));
|
||||
HierarchyObjectWallRight.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToLeft);
|
||||
HierarchyObjectWallRight.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectWallRight.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
IHierarchyObject HierarchyObjectWallLeft = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Wall Left");
|
||||
HierarchyObjectWallLeft.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-532f, 0f), scale: new Vector2D(20f, 328f));
|
||||
HierarchyObjectWallLeft.BehaviourController.AddBehaviour<WallScoreBehaviour>((Action)pongManager.ScoreToRight);
|
||||
HierarchyObjectWallLeft.BehaviourController.AddBehaviour<ShapeBehaviour>(Shape2D.Square);
|
||||
HierarchyObjectWallLeft.BehaviourController.AddBehaviour<RigidBody2D>().IsStatic = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IHierarchyObject HierarchyObjectLeftScoreText = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Score Left");
|
||||
HierarchyObjectLeftScoreText.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-250f, 250f), scale: Vector2D.One * .25f);
|
||||
HierarchyObjectLeftScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(true, spriteFont);
|
||||
|
||||
IHierarchyObject HierarchyObjectRightScoreText = gameManager.InstantiateHierarchyObject<HierarchyObject>().SetHierarchyObject("Score Right");
|
||||
HierarchyObjectRightScoreText.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(250f, 250f), scale: Vector2D.One * .25f);
|
||||
HierarchyObjectRightScoreText.BehaviourController.AddBehaviour<TextScoreBehaviour>(false, spriteFont);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||
Exit();
|
||||
|
||||
gameManager.Update(gameTime.ToEngineTime());
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
protected override void Draw(GameTime gameTime)
|
||||
{
|
||||
GraphicsDevice.Clear(new Color() { R = 32, G = 32, B = 32 });
|
||||
|
||||
// TODO: Add your drawing code here
|
||||
gameManager.PreDraw();
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cameraBehaviour.MatrixTransform);
|
||||
foreach (var displayable in displayableCollector)
|
||||
displayable.Draw(spriteBatch);
|
||||
spriteBatch.End();
|
||||
|
||||
shapeBatch.Begin(cameraBehaviour.MatrixTransform);
|
||||
foreach (var displayableShape in displayableShapeCollector)
|
||||
displayableShape.Draw(shapeBatch);
|
||||
shapeBatch.End();
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.2.1105">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Engine/Engine/Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user