Compare commits

...

47 Commits
v1.3 ... master

Author SHA1 Message Date
J. Fronny d327bfb93f Update .gitlab-ci.yml 2020-08-31 19:26:14 +00:00
J. Fronny 85bed21599 Update .gitlab-ci.yml 2020-07-31 13:25:54 +00:00
J. Fronny a1e08a2273 Add LICENSE 2020-06-27 16:21:05 +00:00
J. Fronny 8ac79b9fb5 Merge branch 'renovate/configure' into 'master'
Configure Renovate

See merge request JFronny/testexetrisathlon!2
2020-06-23 12:06:00 +00:00
Renovate Bot dc337d8b4e
Add renovate.json 2020-06-23 08:51:51 +00:00
J. Fronny 17311cf3e4 Delete main.yml 2020-06-20 16:36:54 +00:00
J. Fronny 9f9ce976a9 Update README.md 2020-06-20 16:36:42 +00:00
J. Fronny 6c8e8c2057 Update .gitlab-ci.yml 2020-06-20 16:35:23 +00:00
J. Fronny ce9ae20a7a Update .gitlab-ci.yml 2020-06-20 16:28:51 +00:00
JFronny f2b827eac3 Cursed, legally questionable commit 2020-06-20 18:27:49 +02:00
J. Fronny 2431338d84 Update .gitlab-ci.yml 2020-06-20 15:51:41 +00:00
J. Fronny 5471318c48 Update .gitlab-ci.yml 2020-06-20 15:31:36 +00:00
J. Fronny 08679ef881 Update .gitlab-ci.yml 2020-06-20 15:20:58 +00:00
J. Fronny 3b660ab4a6 Wut is häpenin 2020-06-20 15:09:59 +00:00
J. Fronny 59ff9d309c Update .gitlab-ci.yml 2020-06-20 14:04:14 +00:00
J. Fronny 9077622b7b Update .gitlab-ci.yml 2020-06-20 13:52:18 +00:00
J. Fronny ab4d83733a Update .gitlab-ci.yml 2020-06-20 13:24:18 +00:00
J. Fronny be220a4610 Update .gitlab-ci.yml 2020-06-20 13:16:20 +00:00
J. Fronny 123c5994a2 Update .gitlab-ci.yml 2020-06-20 12:59:24 +00:00
J. Fronny b568eb1877 Update .gitlab-ci.yml 2020-06-20 12:38:02 +00:00
J. Fronny 94bd2685b6 Update .gitlab-ci.yml 2020-06-20 12:27:07 +00:00
J. Fronny edcec38f62 Update DownloadDataDepsInstall.py 2020-06-20 12:17:13 +00:00
J. Fronny 0e53527aa3 Update .gitlab-ci.yml 2020-06-20 12:08:58 +00:00
J. Fronny 3475274a92 Update .gitlab-ci.yml 2020-06-20 11:02:47 +00:00
J. Fronny 03e7ea4829 Add .gitlab-ci.yml 2020-06-20 10:55:12 +00:00
dependabot-preview[bot] d59218000b Bump Bassoon from 1.1.1 to 1.1.2
Bumps [Bassoon](https://gitlab.com/define-private-public/Bassoon) from 1.1.1 to 1.1.2.
- [Release notes](https://gitlab.com/define-private-public/Bassoon/tags)
- [Commits](https://gitlab.com/define-private-public/Bassoon/compare/Bassoon-1.1.1...Bassoon-1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-06-15 06:52:16 +02:00
J. Fronny 00fc1dacd3
Update main.yml 2020-04-02 15:41:43 +02:00
CreepyCrafter24 dc5a17bc56 Quick hack using ffmpeg to fix linux builds 2020-03-30 16:05:25 +02:00
CreepyCrafter24 0932b0d0d0 Dramatically decrease size 2020-03-29 18:48:58 +02:00
J. Fronny 633c37eb89
Fix ID 2020-03-24 16:18:26 +01:00
J. Fronny 8c65c19a46
Maybe fix icons 2020-03-24 16:11:07 +01:00
J. Fronny 241cdbc4f7
Update README.md 2020-03-24 15:52:36 +01:00
J. Fronny dcd300aae7
Install ffmpeg 2020-03-17 15:30:15 +01:00
J. Fronny 00e0f33a37
Update main.yml 2020-03-17 15:20:51 +01:00
J. Fronny cdfded0e9c
Attempt at CD 2020-03-17 15:18:46 +01:00
CreepyCrafter24 574b85ceb0 Fix beeper, slightly broken (unexpected console output on linux) 2020-03-17 15:08:52 +01:00
CreepyCrafter24 fc043e0219 Improved LinuxSoundManager.cs 2020-03-17 13:45:29 +01:00
CreepyCrafter24 26b067ff04 Start to implement linux sound management 2020-03-17 00:22:58 +01:00
CreepyCrafter24 64f0a3f302 NET Core, needs to be tested on other platforms before release 2020-03-16 22:31:26 +01:00
J. Fronny 02f197ef72
Update README.md 2020-02-24 16:22:36 +01:00
CreepyCrafter24 ee11ee4456 Add alternative soundtrack and rework some stuff 2020-02-24 15:20:42 +01:00
CreepyCrafter24 8e0037aba8 Added score of next level to sidebar 2019-11-22 19:08:50 +01:00
CreepyCrafter24 4578fc3ddb Basically nothing 2019-11-10 17:35:40 +01:00
CreepyCrafter24 17808fbfc6 Implemented Highscore 2019-11-10 17:31:09 +01:00
CreepyCrafter24 4ae676e94e moved volume slider to seperate function 2019-11-10 16:45:13 +01:00
CreepyCrafter24 1bdc3cebba Added a volue slider and code for a Highscore system 2019-11-10 16:42:48 +01:00
CreepyCrafter24 e65562f91a Functions are now way smaller thanks to LINQ 2019-11-10 15:56:18 +01:00
41 changed files with 1117 additions and 558 deletions

82
.gitignore vendored
View File

@ -1,10 +1,9 @@
#Soundtrack data
Soundtrack.aup
Soundtrack_data/*
#Soundtrack data (not enabled because GitLab uses arm64 for windows shared runners with which ffmpeg which is required to generate these files is not compatible)
#testexetrisathlon/*.mp3
# Created by https://www.gitignore.io/api/csharp,visualstudio
# Edit at https://www.gitignore.io/?templates=csharp,visualstudio
# Created by https://www.gitignore.io/api/rider,csharp,visualstudio
# Edit at https://www.gitignore.io/?templates=rider,csharp,visualstudio
### Csharp ###
## Ignore Visual Studio temporary files, build results, and
@ -77,7 +76,6 @@ StyleCopReport.xml
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
@ -357,6 +355,76 @@ healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
### Rider ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### VisualStudio ###
# User-specific files
@ -513,4 +581,4 @@ MigrationBackup/
# Backup folder for Package Reference Convert tool in Visual Studio 2017
# End of https://www.gitignore.io/api/csharp,visualstudio
# End of https://www.gitignore.io/api/rider,csharp,visualstudio

54
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,54 @@
.shared_windows_runners:
tags:
- windows
uptool:
extends:
- .shared_windows_runners
stage: deploy
script: |
mkdir i
cd i
$(new-object System.Net.WebClient).DownloadFile("https://gitlab.com/JFronny/UpTool2/-/jobs/artifacts/master/raw/Installer-generic.zip?job=uptool", "$($(pwd).Path)\Install.zip")
& "C:\Program Files\7-Zip\7z.exe" x .\Install.zip
.\Installer.exe --basic i -p
cd ..
rm -R i
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Install"
uptool --basic add-repo DevTools https://gitlab.com/JFronny/UpTool2/-/snippets/2010392/raw
uptool --basic update
uptool --basic install "UpTool2 package tools"
$Env:Path="$Env:Path;$Env:APPDATA\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app"
#choco install youtube-dl ffmpeg -y --nocolor --no-progress
#refreshenv
#$env:Path=(
# [System.Environment]::GetEnvironmentVariable("Path","Machine"),
# [System.Environment]::GetEnvironmentVariable("Path","User")
#) -match '.' -join ';'
#My python script to auto-generate requirements would be here but arm64 sux
mkdir .\build
dotnet publish -o .\build -c Release
$file = Get-Item $(Resolve-Path .\build\*.exe).Path
pkgtool build --binDir build --mainBin $file --packageFile .\package.zip --noLogo
$asm = $([Reflection.Assembly]::LoadFile($file.DirectoryName + "\" + $file.BaseName + ".dll"))
$asmver = $asm.GetName().Version.ToString()
[System.XML.XMLDocument]$xml=New-Object System.XML.XMLDocument
[System.XML.XMLElement]$app=$xml.CreateElement("app")
$xml.appendChild($app)
$app.appendChild($xml.CreateElement("Name")).InnerText = $asm.GetName().Name
$app.appendChild($xml.CreateElement("Description")).InnerText = "Terminal based Tetris clone"
$app.appendChild($xml.CreateElement("Version")).InnerText = $asmver
$app.appendChild($xml.CreateElement("ID")).InnerText = "9214aca9-af09-441d-8329-612e77347eba"
$app.appendChild($xml.CreateElement("File")).InnerText = $CI_PROJECT_URL + "/-/jobs/" + $CI_JOB_ID + "/artifacts/raw/package.zip"
$app.appendChild($xml.CreateElement("Hash")).InnerText = $(Get-FileHash .\package.zip).Hash
$app.appendChild($xml.CreateElement("MainFile")).InnerText = $file.Name
$app.appendChild($xml.CreateElement("Icon")).InnerText = "https://gitlab.com/JFronny/testexetrisathlon/-/raw/master/testexetrisathlon/tetris_yUxH6t_256px.ico"
echo NULL > app.xml
$xml.save($(gi .\app.xml).Fullname)
artifacts:
paths:
- package.zip
- app.xml
only:
- master

0
.idea/.gitignore vendored Normal file
View File

View File

@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="true" />
</component>
<component name="ProjectNotificationSettings">
<option name="askShowProject" value="false" />
</component>
</project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.testexetrisathlon/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.testexetrisathlon/riderModule.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

62
DownloadData.py Normal file
View File

@ -0,0 +1,62 @@
import os
import os.path
import youtube_dl
import wave
os.chdir("testexetrisathlon")
def dl_vid(url, outfile, filetype):
ydl_opts = {
'outtmpl': outfile,
'noplaylist': True,
'continue_dl': True,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': filetype }]
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([url])
def merge_vids(infiles, outfile):
#lStream = open("list.txt", "w")
#for infile in infiles:
# lStream.write("file '" + infile + ".wav'\n")
#lStream.close()
#os.system("ffmpeg -f concat -i list.txt -c copy " + outfile + ".mp3")
#os.remove("list.txt")
#for infile in infiles:
# os.remove(infile + ".mp3")
data= []
for infile in infiles:
w = wave.open(infile + ".wav", 'rb')
data.append( [w.getparams(), w.readframes(w.getnframes())] )
w.close()
os.remove(infile + ".wav")
output = wave.open(outfile + ".wav", 'wb')
output.setparams(data[0][0])
output.writeframes(data[0][1])
output.writeframes(data[1][1])
output.close()
os.system("ffmpeg -y -i " + outfile + ".wav " + outfile + ".mp3")
os.remove(outfile + ".wav")
if not os.path.isfile("Intro.mp3"):
dl_vid("https://youtu.be/U06jlgpMtQs", "Intro", "mp3")
if not os.path.isfile("InGame1.mp3"):
dl_vid("https://youtu.be/hueJrl83sOQ", "st1", "wav")
dl_vid("https://youtu.be/7gSS4h47rLU", "st2", "wav")
dl_vid("https://youtu.be/NDjDgvXlfVw", "st3", "wav")
merge_vids(["st1", "st2", "st3"], "InGame1")
if not os.path.isfile("InGame2.mp3"):
dl_vid("https://youtu.be/umEDct4BoGc", "st1", "wav")
dl_vid("https://youtu.be/NVpjt9gHlDw", "st2", "wav")
dl_vid("https://youtu.be/zgKazTrhXmI", "st3", "wav")
merge_vids(["st1", "st2", "st3"], "InGame2")
if not os.path.isfile("GameOver.mp3"):
dl_vid("https://youtu.be/J_3Zad-e9f4", "GameOver", "mp3")

View File

@ -0,0 +1,8 @@
import pkg_resources
from subprocess import call
packages = [dist.project_name for dist in pkg_resources.working_set]
if not "youtube-dl" in packages:
packages = ["youtube-dl"] + packages
call("pip install --upgrade " + ' '.join(packages), shell=True)

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 J. Fronny
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1 +1,5 @@
# testexetrisathlon
[![UpTool2](https://img.shields.io/badge/Get%20it-on%20UpTool2-blue)](https://jfronny.gitlab.io/home/uptool)\
To download the files required for building, just run `DownloadData.py`
If you don't have youtube-dl installed (or it is outdated), run `DownloadDataDepsInstall.py`

5
renovate.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": [
"config:base"
]
}

View File

@ -6,14 +6,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testexetrisathlon", "testex
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x86.ActiveCfg = Debug|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x86.Build.0 = Debug|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x86.ActiveCfg = Release|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x86.Build.0 = Release|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Freepik/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=testexetrisathlon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tetrominoe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=winmm/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
testexetrisathlon/Intro.mp3 Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,10 @@
namespace testexetrisathlon
{
public static class SizeSetter
{
public static void SetWindowSize(int width, int height)
{
}
}
}

View File

@ -1,9 +1,10 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Media;
using static System.Console;
using System.Linq;
using System.Reflection;
using testexetrisathlon.SoundManagement;
using static System.Console;
//┌─┐
//│ │
@ -26,184 +27,266 @@ using System.Reflection;
namespace testexetrisathlon
{
class Program
internal static class Program
{
public static string sqr = "■";
public static int[,] grid = new int[23, 10];
public static int[,] droppedtetrominoeLocationGrid = new int[23, 10];
public static Stopwatch dropTimer = new Stopwatch();
public static Stopwatch inputTimer = new Stopwatch();
public static int dropTime, dropRate = 300;
public static bool isDropped = false;
static Tetrominoe tet;
static Tetrominoe nexttet;
public static ConsoleKeyInfo key;
public static bool isKeyPressed = false;
public static int linesCleared = 0, score = 0, level = 1;
static readonly Assembly assembly = Assembly.GetExecutingAssembly();
static ConsoleColor[] colors;
public static bool debug;
public static Random rnd;
static void Main(string[] args)
public const string Sqr = "■";
private const string Intro = "Intro";
private const string GameOver = "GameOver";
public static int[,] Grid = new int[23, 10];
public static int[,] DroppedTetrominoeLocationGrid = new int[23, 10];
private static Stopwatch _dropTimer = new Stopwatch();
private static int _dropTime;
private static int _dropRate = 300;
public static bool IsDropped;
private static Tetrominoe _tet;
private static Tetrominoe _nextTet;
private static ConsoleKeyInfo _key;
private static bool _isKeyPressed;
private static int _linesCleared;
private static int _score;
private static int _level = 1;
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
private static readonly ConsoleColor[] Colors = {BackgroundColor, ForegroundColor};
public static bool Debug;
public static readonly Random Rnd = new Random();
private static ISoundManager _soundManager;
public static IBeeper Beeper;
private static string InGame => SettingsMan.UsingAltTrack ? "InGame2" : "InGame1";
#if DEBUG
private static void Main()
{
rnd = new Random();
colors = new ConsoleColor[2] { BackgroundColor, ForegroundColor };
Debug = true;
#else
private static void Main(string[] args)
{
Debug = args.Contains("debug");
#endif
Beeper = new Beeper();
BackgroundColor = ConsoleColor.Red;
ForegroundColor = ConsoleColor.Yellow;
SetCursorPosition(0, 0);
Clear();
#if (DEBUG)
debug = true;
#else
debug = args.Contains("debug");
#endif
if (debug)
SetWindowSize(50, 40);
new Program().MainN(
new SoundPlayer(assembly.GetManifestResourceStream("testexetrisathlon.Intro.wav")),
new SoundPlayer(assembly.GetManifestResourceStream("testexetrisathlon.InGame.wav")),
new SoundPlayer(assembly.GetManifestResourceStream("testexetrisathlon.GameOver.wav")));
BackgroundColor = colors[0];
ForegroundColor = colors[1];
SetCursorPosition(0, 0);
Clear();
}
enum GameState { exit, menu, game, gameOver }
void MainN(SoundPlayer intro, SoundPlayer inGame, SoundPlayer gameOver)
{
bool playing = true;
GameState state = GameState.menu;
while (playing)
_soundManager = new SoundManager();
_soundManager.Init(new Dictionary<string, string>
{
switch (state)
{
case GameState.menu:
Clear();
gameOver.Stop();
intro.PlayLooping();
SetCursorPosition(0, 1);
Write(
" ▀▀▀██████▄▄▄\r\n" +
" ▀▀▀████▄\r\n" +
" ▄███████▀ ▀███▄\r\n" +
" ▄███████▀ ▀███▄\r\n" +
" ▄████████ ███▄\r\n" +
" ██████████▄ ███▌\r\n" +
" ▀█████▀ ▀███▄ ▐███\r\n" +
" ▀█▀ ▀███▄ ▐███\r\n" +
" ▀███▄ ███▌\r\n" +
" ▄██▄ ▀███▄ ▐███\r\n" +
" ▄██████▄ ▀███▄███\r\n" +
" █████▀▀████▄▄ ▄█████\r\n" +
" ████▀ ▀▀█████▄▄▄▄█████████▄\r\n" +
" ▀▀ ▀▀██████▀▀ ▀▀██\r\n\r\n" +
" testexetrisathlon v." + assembly.GetName().Version.ToString());
SetCursorPosition(10, 18);
WriteLine("Controls: Space");
SetCursorPosition(11, 19);
WriteLine("Up, Down, Right");
SetCursorPosition(11, 20);
WriteLine("Left");
SetCursorPosition(10, 22);
WriteLine("Press s to start");
SetCursorPosition(10, 23);
WriteLine("Press x to exit");
SetCursorPosition(0, 26);
WriteLine("Icon made by Freepik from www.flaticon.com");
string tmp = ReadKey(true).KeyChar.ToString().ToLower();
switch (tmp)
{
case "s":
intro.Stop();
state = GameState.game;
{"Intro", "testexetrisathlon.Intro.mp3"},
{"InGame1", "testexetrisathlon.InGame1.mp3"},
{"InGame2", "testexetrisathlon.InGame2.mp3"},
{"GameOver", "testexetrisathlon.GameOver.mp3"}
});
SizeSetter.SetWindowSize(42, 29);
if (Debug)
SizeSetter.SetWindowSize(50, 40);
SetCursorPosition(0, 0);
bool playing = true;
GameState state = GameState.Menu;
try
{
while (playing)
switch (state)
{
case GameState.Menu:
Clear();
_soundManager.SetCurrent(Intro);
DrawSymbol();
SetCursorPosition(12, 18);
Write("HighScore: " + SettingsMan.HighScore);
SetCursorPosition(12, 20);
Write("Controls: Space");
SetCursorPosition(13, 21);
Write("Up, Down, Right");
SetCursorPosition(13, 22);
Write("Left");
SetCursorPosition(12, 24);
Write("Press s to start");
SetCursorPosition(12, 25);
Write("Press x to exit");
SetCursorPosition(12, 26);
Write("Press v for settings");
SetCursorPosition(0, 28);
Write("Icon made by Freepik from www.flaticon.com");
string tmp = ReadKey(true).KeyChar.ToString().ToLower();
switch (tmp)
{
case "s":
state = GameState.Game;
Clear();
DrawBorder();
break;
case "x":
state = GameState.Exit;
break;
case "v":
SettingsMenu();
break;
}
break;
case GameState.Game:
_soundManager.SetCurrent(InGame);
_dropTimer.Start();
SetCursorPosition(25, 0);
WriteLine("Level " + _level);
SetCursorPosition(25, 1);
WriteLine("Score " + _score + "/" + (Math.Pow(_level, 2) * 100));
SetCursorPosition(25, 2);
WriteLine("LinesCleared " + _linesCleared);
SetCursorPosition(25, 4);
WriteLine("HighScore " + SettingsMan.HighScore);
_nextTet = new Tetrominoe();
_tet = _nextTet;
_tet.Spawn();
_nextTet = new Tetrominoe();
Update();
state = GameState.GameOver;
break;
case GameState.GameOver:
SettingsMan.HighScore = _score;
_soundManager.SetCurrent(GameOver);
string input = "";
while (input != "y" && input != "n")
{
Clear();
DrawBorder();
break;
case "x":
state = GameState.exit;
break;
}
break;
case GameState.game:
inGame.PlayLooping();
dropTimer.Start();
SetCursorPosition(25, 0);
WriteLine("Level " + level);
SetCursorPosition(25, 1);
WriteLine("Score " + score);
SetCursorPosition(25, 2);
WriteLine("LinesCleared " + linesCleared);
nexttet = new Tetrominoe();
tet = nexttet;
tet.Spawn();
nexttet = new Tetrominoe();
Update();
inGame.Stop();
state = GameState.gameOver;
break;
case GameState.gameOver:
gameOver.PlayLooping();
string input = "";
while ((input != "y") && (input != "n"))
{
Draw();
SetCursorPosition(0, 0);
WriteLine("┌───────────────────┐");
WriteLine("│ Game Over │");
WriteLine("│ Replay? (Y/N) │");
WriteLine("├───────────────────┤");
input = ReadKey().KeyChar.ToString().ToLower();
}
Grid = new int[23, 10];
DroppedTetrominoeLocationGrid = new int[23, 10];
_dropTimer = new Stopwatch();
_dropRate = 300;
IsDropped = false;
_isKeyPressed = false;
_linesCleared = 0;
_score = 0;
_level = 1;
GC.Collect();
Clear();
DrawBorder();
Draw();
SetCursorPosition(0, 0);
WriteLine("┌───────────────────┐");
WriteLine("│ Game Over │");
WriteLine("│ Replay? (Y/N) │");
WriteLine("├───────────────────┤");
input = ReadKey().KeyChar.ToString().ToLower();
state = input == "y" ? GameState.Game : GameState.Menu;
break;
case GameState.Exit:
playing = false;
break;
default: throw new ArgumentOutOfRangeException();
}
}
finally
{
_soundManager.Dispose();
}
BackgroundColor = Colors[0];
ForegroundColor = Colors[1];
SetCursorPosition(0, 0);
Clear();
Beeper.Dispose();
}
private static void DrawSymbol()
{
SetCursorPosition(0, 1);
Write(
" ▀▀▀██████▄▄▄\r\n" +
" ▀▀▀████▄\r\n" +
" ▄███████▀ ▀███▄\r\n" +
" ▄███████▀ ▀███▄\r\n" +
" ▄████████ ███▄\r\n" +
" ██████████▄ ███▌\r\n" +
" ▀█████▀ ▀███▄ ▐███\r\n" +
" ▀█▀ ▀███▄ ▐███\r\n" +
" ▀███▄ ███▌\r\n" +
" ▄██▄ ▀███▄ ▐███\r\n" +
" ▄██████▄ ▀███▄███\r\n" +
" █████▀▀████▄▄ ▄█████\r\n" +
" ████▀ ▀▀█████▄▄▄▄█████████▄\r\n" +
" ▀▀ ▀▀██████▀▀ ▀▀██\r\n\r\n" +
" testexetrisathlon v." + Assembly.GetName().Version);
}
private static void SettingsMenu()
{
Clear();
DrawSymbol();
bool barActive = true;
int currentSetting = 0;
while (barActive)
{
bool curr = SettingsMan.UsingAltTrack;
SetCursorPosition(3, 20);
ForegroundColor = currentSetting == 0 ? ConsoleColor.White : ConsoleColor.Yellow;
Write("Volume: " + new string('=', SettingsMan.Volume * 2) + "[" + SettingsMan.Volume.ToString("00") +
"]" + new string('=', 20 - (SettingsMan.Volume * 2)));
SetCursorPosition(5, 22);
ForegroundColor = currentSetting == 1 ? ConsoleColor.White : ConsoleColor.Yellow;
Write($"{(curr ? " Using" : "Not using")} alternative soundtrack ");
ForegroundColor = ConsoleColor.Yellow;
switch (currentSetting)
{
case 0:
switch (ReadKey().Key)
{
case ConsoleKey.LeftArrow:
SettingsMan.Volume--;
break;
case ConsoleKey.RightArrow:
SettingsMan.Volume++;
break;
case ConsoleKey.Enter:
barActive = false;
break;
case ConsoleKey.Tab:
currentSetting = 1;
break;
}
grid = new int[23, 10];
droppedtetrominoeLocationGrid = new int[23, 10];
dropTimer = new Stopwatch();
inputTimer = new Stopwatch();
dropRate = 300;
isDropped = false;
isKeyPressed = false;
linesCleared = 0;
score = 0;
level = 1;
GC.Collect();
Clear();
DrawBorder();
if (input == "y")
state = GameState.game;
else
state = GameState.menu;
break;
default:
playing = false;
case 1:
switch (ReadKey().Key)
{
case ConsoleKey.LeftArrow:
case ConsoleKey.RightArrow:
case ConsoleKey.Spacebar:
SettingsMan.UsingAltTrack = !curr;
break;
case ConsoleKey.Enter:
barActive = false;
break;
case ConsoleKey.Tab:
currentSetting = 0;
break;
}
break;
}
_soundManager.SetVolume(SettingsMan.Volume * 10);
}
}
private static void Update()
{
while (true)
{
dropTime = (int)dropTimer.ElapsedMilliseconds;
if (dropTime > dropRate)
_dropTime = (int) _dropTimer.ElapsedMilliseconds;
if (_dropTime > _dropRate)
{
dropTime = 0; dropTimer.Restart(); tet.Drop();
_dropTime = 0;
_dropTimer.Restart();
_tet.Drop();
}
if (isDropped == true)
if (IsDropped)
{
tet = nexttet;
nexttet = new Tetrominoe();
tet.Spawn();
isDropped = false;
score += 10;
_tet = _nextTet;
_nextTet = new Tetrominoe();
_tet.Spawn();
IsDropped = false;
_score += 10;
}
int j; for (j = 0; j < 10; j++)
{
if (droppedtetrominoeLocationGrid[0, j] == 1)
for (int j = 0; j < 10; j++)
if (DroppedTetrominoeLocationGrid[0, j] == 1)
return;
}
if (debug)
if (Debug)
{
SetCursorPosition(0, 25);
WriteLine("!DEBUG MODE ENABLED!");
@ -212,105 +295,88 @@ namespace testexetrisathlon
ClearBlock();
}
}
private static void ClearBlock()
{
int combo = 0;
for (int i = 0; i < 23; i++)
{
int j; for (j = 0; j < 10; j++)
if (Enumerable.Range(0, 10).All(s => DroppedTetrominoeLocationGrid[i, s] != 0))
{
if (droppedtetrominoeLocationGrid[i, j] == 0)
break;
}
if (j == 10)
{
linesCleared++;
_linesCleared++;
combo++;
Beep(400, 200);
for (j = 0; j < 10; j++)
{
droppedtetrominoeLocationGrid[i, j] = 0;
}
int[,] newdroppedtetrominoeLocationGrid = new int[23, 10];
Beeper.Beep(400, 200);
for (int j = 0; j < 10; j++) DroppedTetrominoeLocationGrid[i, j] = 0;
int[,] newDroppedTetrominoeLocationGrid = new int[23, 10];
for (int k = 1; k < i; k++)
{
for (int l = 0; l < 10; l++)
{
newdroppedtetrominoeLocationGrid[k + 1, l] = droppedtetrominoeLocationGrid[k, l];
}
}
for (int l = 0; l < 10; l++)
newDroppedTetrominoeLocationGrid[k + 1, l] = DroppedTetrominoeLocationGrid[k, l];
for (int k = 1; k < i; k++)
{
for (int l = 0; l < 10; l++)
{
droppedtetrominoeLocationGrid[k, l] = 0;
}
}
for (int l = 0; l < 10; l++)
DroppedTetrominoeLocationGrid[k, l] = 0;
for (int k = 0; k < 23; k++)
for (int l = 0; l < 10; l++)
if (newdroppedtetrominoeLocationGrid[k, l] == 1)
droppedtetrominoeLocationGrid[k, l] = 1;
for (int l = 0; l < 10; l++)
if (newDroppedTetrominoeLocationGrid[k, l] == 1)
DroppedTetrominoeLocationGrid[k, l] = 1;
Draw();
}
}
score += (int)Math.Round(Math.Sqrt(Math.Max(combo * 50 - 50, 0)) * 5);
level = (int)Math.Round(Math.Sqrt(score * 0.01)) + 1;
dropRate = 300 - 22 * level;
_score += (int) Math.Round(Math.Sqrt(Math.Max((combo * 50) - 50, 0)) * 5);
_level = (int) Math.Round(Math.Sqrt(_score * 0.01)) + 1;
_dropRate = 300 - (22 * _level);
}
private static void Input()
{
isKeyPressed = KeyAvailable;
_isKeyPressed = KeyAvailable;
SetCursorPosition(0, 24);
if (isKeyPressed)
key = ReadKey();
if (key.Key == ConsoleKey.LeftArrow & !tet.isSomethingLeft() & isKeyPressed)
if (_isKeyPressed)
_key = ReadKey();
if ((_key.Key == ConsoleKey.LeftArrow) & !_tet.IsSomethingLeft() & _isKeyPressed)
{
for (int i = 0; i < 4; i++)
tet.location[i][1] -= 1;
tet.Update();
_tet.Location[i][1] -= 1;
_tet.Update();
}
else if (key.Key == ConsoleKey.RightArrow & !tet.isSomethingRight() & isKeyPressed)
else if ((_key.Key == ConsoleKey.RightArrow) & !_tet.IsSomethingRight() & _isKeyPressed)
{
for (int i = 0; i < 4; i++)
tet.location[i][1] += 1;
tet.Update();
}
if (key.Key == ConsoleKey.DownArrow & isKeyPressed)
tet.Drop();
if (key.Key == ConsoleKey.UpArrow & isKeyPressed)
for (; tet.isSomethingBelow() != true;)
tet.Drop();
if (key.Key == ConsoleKey.Spacebar & isKeyPressed)
{
tet.Rotate();
tet.Update();
_tet.Location[i][1] += 1;
_tet.Update();
}
if ((_key.Key == ConsoleKey.DownArrow) & _isKeyPressed)
_tet.Drop();
if ((_key.Key == ConsoleKey.UpArrow) & _isKeyPressed)
for (; _tet.IsSomethingBelow != true;)
_tet.Drop();
if (!((_key.Key == ConsoleKey.Spacebar) & _isKeyPressed)) return;
_tet.Rotate();
_tet.Update();
}
public static void Draw()
{
for (int i = 0; i < 23; ++i)
for (int j = 0; j < 10; j++)
{
for (int j = 0; j < 10; j++)
SetCursorPosition((2 * j) + 1, i);
if ((Grid[i, j] == 1) | (DroppedTetrominoeLocationGrid[i, j] == 1))
{
SetCursorPosition(1 + 2 * j, i);
if (grid[i, j] == 1 | droppedtetrominoeLocationGrid[i, j] == 1)
{
SetCursorPosition(1 + 2 * j, i);
Write(sqr);
}
else
{
Write(" ");
}
SetCursorPosition((2 * j) + 1, i);
Write(Sqr);
}
else
{
Write(" ");
}
}
SetCursorPosition(25, 0);
WriteLine("Level " + level);
WriteLine("Level " + _level);
SetCursorPosition(25, 1);
WriteLine("Score " + score);
WriteLine("Score " + _score + "/" + (Math.Pow(_level, 2) * 100));
SetCursorPosition(25, 2);
WriteLine("LinesCleared " + linesCleared);
WriteLine("LinesCleared " + _linesCleared);
DrawBorder();
}
public static void DrawBorder()
{
for (int lengthCount = 0; lengthCount <= 22; lengthCount++)
@ -322,11 +388,16 @@ namespace testexetrisathlon
}
SetCursorPosition(0, 23);
Write("└");
for (int widthCount = 0; widthCount <= 18; widthCount++)
{
Write("─");
}
for (int widthCount = 0; widthCount <= 18; widthCount++) Write("─");
Write("┘");
}
private enum GameState
{
Exit,
Menu,
Game,
GameOver
}
}
}
}

View File

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
@ -23,4 +22,4 @@ using System.Runtime.CompilerServices;
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]
//[assembly: AssemblyKeyFile("")]

View File

@ -0,0 +1,65 @@
using System;
using System.IO;
using System.Reflection;
using System.Xml.Linq;
namespace testexetrisathlon
{
internal static class SettingsMan
{
private static readonly string XmlFile =
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Save.xml");
public static int Volume
{
get => ToRange(int.Parse(Load().Element("Volume").Value), 0, 10);
set
{
XElement doc = Load();
doc.Element("Volume").Value = ToRange(value, 0, 10).ToString();
doc.Save();
}
}
public static int HighScore
{
get => int.Parse(Load().Element("HighScore").Value);
set
{
XElement doc = Load();
doc.Element("HighScore").Value = value.ToString();
doc.Save();
}
}
public static bool UsingAltTrack
{
get => bool.Parse(Load().Element("AltTrack").Value);
set
{
XElement doc = Load();
doc.Element("AltTrack").Value = value.ToString();
doc.Save();
}
}
private static void Save(this XElement doc) => doc.Save(XmlFile);
private static XElement Load()
{
if (!File.Exists(XmlFile))
new XElement("Save").Save(XmlFile);
XElement doc = XDocument.Load(XmlFile).Root;
if (doc.Element("Volume") == null)
doc.Add(new XElement("Volume", 10));
if (doc.Element("HighScore") == null)
doc.Add(new XElement("HighScore", 10));
if (doc.Element("AltTrack") == null)
doc.Add(new XElement("AltTrack", false));
return doc;
}
private static int ToRange(int value, int rangeStart, int rangeEnd) =>
Math.Min(Math.Max(value, rangeStart), rangeEnd);
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace testexetrisathlon.SoundManagement
{
public interface IBeeper : IDisposable
{
public void Beep(int frequency, int duration);
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace testexetrisathlon.SoundManagement
{
public interface ISoundManager : IDisposable
{
public void Init(Dictionary<string, string> manifestResources);
public void SetCurrent(string id);
public void SetVolume(int percent);
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using Bassoon;
namespace testexetrisathlon.SoundManagement
{
public class Beeper : IBeeper
{
private static readonly Dictionary<Tuple<int, int>, Tuple<string, Sound>> Beeps = new Dictionary<Tuple<int, int>, Tuple<string, Sound>>();
public void Beep(int frequency, int duration)
{
Tuple<int, int> key = new Tuple<int, int>(frequency, duration);
if (!Beeps.ContainsKey(key))
{
string file = Path.GetTempFileName();
File.Move(file, Path.ChangeExtension(file, "wav"));
file = Path.ChangeExtension(file, "wav");
File.WriteAllBytes(file, BeepBeep(1000, frequency, duration));
Beeps.Add(key, new Tuple<string, Sound>(file, new Sound(file)));
}
Beeps[key].Item2.Cursor = 0;
Beeps[key].Item2.Play();
Console.Clear();
}
private static byte[] BeepBeep(int amplitude, int frequency, int duration)
{
double a = ((amplitude * Math.Pow(2, 15)) / 1000) - 1;
double deltaFt = (2 * Math.PI * frequency) / 44100.0;
int samples = (441 * duration) / 10;
int bytes = samples * 4;
int[] hdr = {0X46464952, 36 + bytes, 0X45564157, 0X20746D66, 16, 0X20001, 44100, 176400, 0X100004, 0X61746164, bytes};
using MemoryStream ms = new MemoryStream(44 + bytes);
using BinaryWriter bw = new BinaryWriter(ms);
for (int I = 0; I < hdr.Length; I++) bw.Write(hdr[I]);
for (int T = 0; T < samples; T++)
{
short sample = Convert.ToInt16(a * Math.Sin(deltaFt * T));
bw.Write(sample);
bw.Write(sample);
}
bw.Flush();
ms.Seek(0, SeekOrigin.Begin);
return ms.ToArray();
}
public void Dispose()
{
foreach (Tuple<string, Sound> file in Beeps.Values) File.Delete(file.Item1);
}
}
}

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Bassoon;
namespace testexetrisathlon.SoundManagement
{
public class SoundManager : ISoundManager
{
private BassoonEngine _bassoon;
private Dictionary<string, Sound> _loadedSounds;
private Dictionary<string, string> _files;
private string _current;
private int _volume = 100;
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
public void Dispose()
{
foreach (Sound sound in _loadedSounds.Values) sound.Dispose();
_bassoon.Dispose();
foreach (string file in _files.Values) File.Delete(file);
}
public void Init(Dictionary<string, string> manifestResources)
{
_bassoon = new BassoonEngine();
_files = new Dictionary<string, string>();
_loadedSounds = new Dictionary<string, Sound>();
foreach ((string name, string key) in manifestResources)
{
string file = Path.GetTempFileName();
File.Move(file, Path.ChangeExtension(file, "mp3"));
file = Path.ChangeExtension(file, "mp3");
using (Stream resource = Assembly.GetManifestResourceStream(key))
{
using FileStream fileStream = File.Create(file);
resource.Seek(0, SeekOrigin.Begin);
resource.CopyTo(fileStream);
}
Process.Start(new ProcessStartInfo{FileName = "ffmpeg", Arguments = $"-i {file} {Path.ChangeExtension(file, "wav")}", WorkingDirectory = Path.GetTempPath()}).WaitForExit();
File.Delete(file);
file = Path.ChangeExtension(file, "wav");
_files.Add(name, file);
_loadedSounds.Add(name, new Sound(file));
}
Console.Clear();
}
public void SetCurrent(string id)
{
if (_current == id) return;
if (!string.IsNullOrWhiteSpace(_current))
{
_loadedSounds[_current].Pause();
_loadedSounds[_current].Cursor = 0;
}
_current = id;
_loadedSounds[_current].Play();
Console.Clear();
}
public void SetVolume(int percent)
{
_volume = percent;
foreach (Sound sound in _loadedSounds.Values) sound.Volume = _volume / 100f;
}
}
}

View File

@ -0,0 +1,48 @@
using NAudio.Wave;
namespace testexetrisathlon.SoundManagement
{
public class LoopStream : WaveStream
{
private readonly WaveStream _sourceStream;
public LoopStream(WaveStream sourceStream)
{
_sourceStream = sourceStream;
EnableLooping = true;
}
private bool EnableLooping { get; }
public override WaveFormat WaveFormat => _sourceStream.WaveFormat;
public override long Length => _sourceStream.Length;
public override long Position
{
get => _sourceStream.Position;
set => _sourceStream.Position = value;
}
public override int Read(byte[] buffer, int offset, int count)
{
int totalBytesRead = 0;
while (totalBytesRead < count)
{
int bytesRead = _sourceStream.Read(buffer, offset + totalBytesRead, count - totalBytesRead);
if (bytesRead == 0)
{
if (_sourceStream.Position == 0 || !EnableLooping) break;
_sourceStream.Position = 0;
}
totalBytesRead += bytesRead;
}
return totalBytesRead;
}
public new void Dispose()
{
base.Dispose();
_sourceStream.Dispose();
}
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace testexetrisathlon.SoundManagement
{
public class Beeper : IBeeper
{
public void Beep(int frequency, int duration) => Console.Beep(frequency, duration);
public void Dispose()
{
}
}
}

View File

@ -0,0 +1,54 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using NAudio.Wave;
namespace testexetrisathlon.SoundManagement
{
public sealed class SoundManager : ISoundManager
{
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
private WaveStream _current;
private string _currentId;
private Dictionary<string, LoopStream> _loadedSounds;
private WaveOutEvent _output;
public void Init(Dictionary<string, string> manifestResources)
{
_output = new WaveOutEvent();
_loadedSounds = manifestResources.ToDictionary(s => s.Key,
s => new LoopStream(new WaveFileReader(Mp3ToWav(Assembly.GetManifestResourceStream(s.Value)))));
}
public void SetCurrent(string id)
{
if (_currentId == id) return;
_currentId = id;
if (_current != null)
_current.Position = 0;
_current = _loadedSounds[id];
_output.Stop();
_output.Init(_current);
_output.Play();
}
public void SetVolume(int percent) => _output.Volume = percent / 100f;
public void Dispose()
{
foreach (LoopStream reader in _loadedSounds.Values) reader.Dispose();
_output.Dispose();
}
private static MemoryStream Mp3ToWav(Stream mp3File)
{
using Mp3FileReader reader = new Mp3FileReader(mp3File);
using WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader);
MemoryStream ms = new MemoryStream();
WaveFileWriter.WriteWavFileToStream(ms, pcmStream);
ms.Position = 0;
return ms;
}
}
}

View File

@ -1,307 +1,203 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using testexetrisathlon.SoundManagement;
using static System.Console;
#pragma warning disable IDE1006
namespace testexetrisathlon
{
public class Tetrominoe
{
public static int[,] I = new int[1, 4] { { 1, 1, 1, 1 } };
private static readonly int[,] I = {{1, 1, 1, 1}};
public static int[,] O = new int[2, 2] { { 1, 1 },
{ 1, 1 } };
private static readonly int[,] O =
{
{1, 1},
{1, 1}
};
public static int[,] T = new int[2, 3] { { 0, 1, 0 },
{ 1, 1, 1 } };
private static readonly int[,] T =
{
{0, 1, 0},
{1, 1, 1}
};
public static int[,] S = new int[2, 3] { { 0, 1, 1 },
{ 1, 1, 0 } };
private static readonly int[,] S =
{
{0, 1, 1},
{1, 1, 0}
};
public static int[,] Z = new int[2, 3] { { 1, 1, 0 },
{ 0, 1, 1 } };
private static readonly int[,] Z =
{
{1, 1, 0},
{0, 1, 1}
};
public static int[,] J = new int[2, 3] { { 1, 0, 0 },
{ 1, 1, 1 } };
private static readonly int[,] J =
{
{1, 0, 0},
{1, 1, 1}
};
private static readonly int[,] L =
{
{0, 0, 1},
{1, 1, 1}
};
private static readonly List<int[,]> TetrominoeList = new List<int[,]> {I, O, T, S, Z, J, L};
private readonly int[,] _shape;
public List<int[]> Location = new List<int[]>();
public static int[,] L = new int[2, 3] { { 0, 0, 1 },
{ 1, 1, 1 } };
public static List<int[,]> tetrominoes = new List<int[,]>() { I, O, T, S, Z, J, L };
private readonly int[,] shape;
public List<int[]> location = new List<int[]>();
public Tetrominoe()
{
shape = tetrominoes[Program.rnd.Next(0, tetrominoes.Count)];
for (int i = 23; i < 33; ++i)
_shape = TetrominoeList[Program.Rnd.Next(0, TetrominoeList.Count)];
for (int i = 0; i < 7; i++)
for (int j = 0; j < 2; j++)
{
for (int j = 3; j < 10; j++)
{
SetCursorPosition(i, j);
Write(" ");
}
SetCursorPosition(i + 26, j + 6);
Write(Program.Debug ? "X" : " ");
}
Program.DrawBorder();
for (int i = 0; i < shape.GetLength(0); i++)
{
for (int j = 0; j < shape.GetLength(1); j++)
for (int i = 0; i < _shape.GetLength(0); i++)
for (int j = 0; j < _shape.GetLength(1); j++)
if (_shape[i, j] == 1)
{
if (shape[i, j] == 1)
{
SetCursorPosition(((10 - shape.GetLength(1)) / 2 + j) * 2 + 20, i + 5);
Write(Program.sqr);
}
SetCursorPosition((30 - _shape.GetLength(1)) + (2 * j), i + 6);
Write(Program.Sqr);
}
}
}
public bool IsSomethingBelow => Location.Any(s => s[0] + 1 >= 23 || (s[0] + 1 < 23) &
(Program.DroppedTetrominoeLocationGrid[s[0] + 1, s[1]] == 1));
public void Spawn()
{
for (int i = 0; i < shape.GetLength(0); i++)
{
for (int j = 0; j < shape.GetLength(1); j++)
{
if (shape[i, j] == 1)
{
location.Add(new int[] { i, (10 - shape.GetLength(1)) / 2 + j });
}
}
}
for (int i = 0; i < _shape.GetLength(0); i++)
for (int j = 0; j < _shape.GetLength(1); j++)
if (_shape[i, j] == 1)
Location.Add(new[] {i, (5 - (_shape.GetLength(1) / 2)) + j});
Update();
}
public void Drop()
{
if (isSomethingBelow())
if (IsSomethingBelow)
{
for (int i = 0; i < 4; i++)
{
Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] = 1;
}
Program.isDropped = true;
Beep(800, 200);
Location.ForEach(s => Program.DroppedTetrominoeLocationGrid[s[0], s[1]] = 1);
Program.IsDropped = true;
Program.Beeper.Beep(800, 200);
}
else
{
for (int numCount = 0; numCount < 4; numCount++)
{
location[numCount][0] += 1;
}
Location.ForEach(s => s[0]++);
Update();
}
}
public void Rotate()
{
List<int[]> templocation = new List<int[]>();
for (int i = 0; i < shape.GetLength(0); i++)
{
for (int j = 0; j < shape.GetLength(1); j++)
{
if (shape[i, j] == 1)
{
templocation.Add(new int[] { i, (10 - shape.GetLength(1)) / 2 + j });
}
}
}
if (shape == tetrominoes[0])
{
for (int i = 0; i < location.Count; i++)
{
templocation[i] = TransformMatrix(location[i], location[2]);
}
}
else if (shape == tetrominoes[3])
{
for (int i = 0; i < location.Count; i++)
{
templocation[i] = TransformMatrix(location[i], location[3]);
}
}
else if (shape == tetrominoes[1])
List<int[]> tempLocation = new List<int[]>();
for (int i = 0; i < _shape.GetLength(0); i++)
for (int j = 0; j < _shape.GetLength(1); j++)
if (_shape[i, j] == 1)
tempLocation.Add(new[] {i, ((10 - _shape.GetLength(1)) / 2) + j});
if (_shape == TetrominoeList[1])
return;
else
for (int i = 0; i < Location.Count; i++)
tempLocation[i] = TransformMatrix(Location[i], Location[_shape == TetrominoeList[3] ? 3 : 2]);
for (int count = 0;
(IsOverlayLeft(tempLocation) != false) | (IsOverlayRight(tempLocation) != false) |
(IsOverlayBelow(tempLocation) != false);
count++)
{
for (int i = 0; i < location.Count; i++)
{
templocation[i] = TransformMatrix(location[i], location[2]);
}
}
for (int count = 0; isOverlayLeft(templocation) != false | isOverlayRight(templocation) != false | isOverlayBelow(templocation) != false; count++)
{
if (isOverlayLeft(templocation) == true)
{
for (int i = 0; i < location.Count; i++)
{
templocation[i][1] += 1;
}
}
if (isOverlayRight(templocation) == true)
{
for (int i = 0; i < location.Count; i++)
{
templocation[i][1] -= 1;
}
}
if (isOverlayBelow(templocation) == true)
{
for (int i = 0; i < location.Count; i++)
{
templocation[i][0] -= 1;
}
}
if (IsOverlayLeft(tempLocation) == true)
for (int i = 0; i < Location.Count; i++)
tempLocation[i][1]++;
if (IsOverlayRight(tempLocation) == true)
for (int i = 0; i < Location.Count; i++)
tempLocation[i][1]--;
if (IsOverlayBelow(tempLocation) == true)
for (int i = 0; i < Location.Count; i++)
tempLocation[i][0]--;
if (count == 3)
{
return;
}
}
location = templocation;
Location = tempLocation;
}
public bool notFalse(bool? inp) => (inp ?? true);
public int[] TransformMatrix(int[] coord, int[] axis) => new int[] { axis[0] - axis[1] + coord[1], axis[0] + axis[1] - coord[0] };
public bool isSomethingBelow()
private static int[] TransformMatrix(IReadOnlyList<int> coords, IReadOnlyList<int> axis) =>
new[] {(axis[0] - axis[1]) + coords[1], (axis[0] + axis[1]) - coords[0]};
private static bool? IsOverlayBelow(IReadOnlyList<int[]> location)
{
List<int> yCoords = new List<int>();
for (int i = 0; i < 4; i++)
{
if (location[i][0] + 1 >= 23)
return true;
if (location[i][0] + 1 < 23 & Program.droppedtetrominoeLocationGrid[location[i][0] + 1, location[i][1]] == 1)
return true;
}
return false;
}
public bool? isOverlayBelow(List<int[]> location)
{
List<int> ycoords = new List<int>();
for (int i = 0; i < 4; i++)
{
ycoords.Add(location[i][0]);
yCoords.Add(location[i][0]);
if (location[i][0] >= 23)
return true;
if (location[i][0] < 0 | location[i][1] < 0 | location[i][1] > 9)
if ((location[i][0] < 0) | (location[i][1] < 0) | (location[i][1] > 9))
return null;
}
for (int i = 0; i < 4; i++)
{
if (ycoords.Max() - ycoords.Min() == 3)
{
if ((ycoords.Max() == location[i][0] | ycoords.Max() - 1 == location[i][0]) & (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1))
{
return true;
}
}
else
{
if ((ycoords.Max() == location[i][0]) & (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1))
{
return true;
}
}
}
return false;
return location.Any(s =>
yCoords.Max() - yCoords.Min() == 3
? ((yCoords.Max() == s[0]) | (yCoords.Max() - 1 == s[0])) &
(Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1)
: (yCoords.Max() == s[0]) & (Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1));
}
public bool isSomethingLeft()
public bool IsSomethingLeft() =>
Location.Any(s => s[1] == 0 || Program.DroppedTetrominoeLocationGrid[s[0], s[1] - 1] == 1);
private static bool? IsOverlayLeft(IReadOnlyList<int[]> location)
{
List<int> xCoords = new List<int>();
xCoords.AddRange(location.Select(s => s[1]));
for (int i = 0; i < 4; i++)
{
if (location[i][1] == 0)
return true;
else if (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1] - 1] == 1)
return true;
}
return false;
}
public bool? isOverlayLeft(List<int[]> location)
{
List<int> xcoords = new List<int>();
for (int i = 0; i < 4; i++)
{
xcoords.Add(location[i][1]);
if (location[i][1] < 0)
return true;
if (location[i][1] > 9)
return false;
if (location[i][0] >= 23 | location[i][0] < 0)
if ((location[i][0] >= 23) | (location[i][0] < 0))
return null;
}
for (int i = 0; i < 4; i++)
{
if (xcoords.Max() - xcoords.Min() == 3)
{
if (xcoords.Min() == location[i][1] | xcoords.Min() + 1 == location[i][1])
{
if (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1)
{
return true;
}
}
}
else
{
if (xcoords.Min() == location[i][1])
{
if (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1)
{
return true;
}
}
}
}
return false;
return location.Any(s => xCoords.Max() - xCoords.Min() == 3
? (xCoords.Min() == s[1]) | (xCoords.Min() + 1 == s[1]) &&
Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1
: xCoords.Min() == s[1] && Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1);
}
public bool isSomethingRight()
public bool IsSomethingRight() =>
Location.Any(s => s[1] == 9 || Program.DroppedTetrominoeLocationGrid[s[0], s[1] + 1] == 1);
private static bool? IsOverlayRight(IReadOnlyList<int[]> location)
{
List<int> xCoords = new List<int>();
xCoords.AddRange(location.Select(s => s[1]));
for (int i = 0; i < 4; i++)
{
if (location[i][1] == 9)
return true;
else if (Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1] + 1] == 1)
return true;
}
return false;
}
public bool? isOverlayRight(List<int[]> location)
{
List<int> xcoords = new List<int>();
for (int i = 0; i < 4; i++)
{
xcoords.Add(location[i][1]);
if (location[i][1] > 9)
return true;
if (location[i][1] < 0)
return false;
if (location[i][0] >= 23 | location[i][0] < 0)
if ((location[i][0] >= 23) | (location[i][0] < 0))
return null;
}
for (int i = 0; i < 4; i++)
{
if (xcoords.Max() - xcoords.Min() == 3)
{
if ((xcoords.Max() == location[i][1] | xcoords.Max() - 1 == location[i][1]) & Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1)
{
return true;
}
}
else
{
if (xcoords.Max() == location[i][1] & Program.droppedtetrominoeLocationGrid[location[i][0], location[i][1]] == 1)
{
return true;
}
}
}
return false;
return location.Any(s => xCoords.Max() - xCoords.Min() == 3
? ((xCoords.Max() == s[1]) | (xCoords.Max() - 1 == s[1])) &
(Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1)
: (xCoords.Max() == s[1]) & (Program.DroppedTetrominoeLocationGrid[s[0], s[1]] == 1));
}
public void Update()
{
for (int i = 0; i < 23; i++)
{
for (int j = 0; j < 10; j++)
{
Program.grid[i, j] = 0;
}
}
for (int i = 0; i < 4; i++)
{
Program.grid[location[i][0], location[i][1]] = 1;
}
for (int j = 0; j < 10; j++)
Program.Grid[i, j] = 0;
Location.ForEach(s => Program.Grid[s[0], s[1]] = 1);
Program.Draw();
}
}
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace testexetrisathlon
{
public static class SizeSetter
{
public static void SetWindowSize(int width, int height) => Console.SetWindowSize(width, height);
}
}

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@ -1,91 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}</ProjectGuid>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>testexetrisathlon</RootNamespace>
<AssemblyName>testexetrisathlon</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
<LangVersion>8</LangVersion>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<Optimize>true</Optimize>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<Optimize>true</Optimize>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
<PropertyGroup>
<PostBuildEvent Condition="'$(OS)' == 'Windows_NT'">
if exist "$(SolutionDir)Data\pkgtool.exe" ($(SolutionDir)Data\pkgtool.exe build --noLogo --binDir .) else if exist "%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" ("%appdata%\UpTool2\Apps\0e35d154-d0d3-45e0-b080-62f521263a44\app\pkgtool.exe" build --noLogo --binDir .) else echo Cound not find Package build tools, skipping
</PostBuildEvent>
<PostBuildEvent Condition="'$(OS)' != 'Windows_NT'">
if [[ -f "$(SolutionDir)Data/pkgtool.exe" ]]; then $(SolutionDir)Data/pkgtool.exe build --noLogo --binDir .; else echo Cound not find Package build tools, skipping; fi
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>tetris_yUxH6t_256px.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tetrominoe.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="GameOver.wav" />
<EmbeddedResource Include="InGame.wav" />
<EmbeddedResource Include="Intro.wav" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="GameOver.mp3" />
<EmbeddedResource Include="InGame1.mp3" />
<EmbeddedResource Include="InGame2.mp3" />
<EmbeddedResource Include="Intro.mp3" />
<Content Include="tetris_yUxH6t_256px.ico" />
<Compile Remove="SoundManagement/LinuxSoundManager.cs" Condition="'$(OS)' == 'Windows_NT'" />
<Compile Remove="SoundManagement/WindowsSoundManager.cs" Condition="'$(OS)' != 'Windows_NT'" />
<Compile Remove="SoundManagement/LoopStream.cs" Condition="'$(OS)' != 'Windows_NT'" />
<Compile Remove="SoundManagement/LinuxBeeper.cs" Condition="'$(OS)' == 'Windows_NT'" />
<Compile Remove="SoundManagement/WindowsBeeper.cs" Condition="'$(OS)' != 'Windows_NT'" />
<Compile Remove="LinuxSizeSetter.cs" Condition="'$(OS)' == 'Windows_NT'" />
<Compile Remove="WindowsSizeSetter.cs" Condition="'$(OS)' != 'Windows_NT'" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Bassoon" Version="1.1.2" Condition="'$(OS)' != 'Windows_NT'" />
<PackageReference Include="NAudio" Version="1.10.0" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testexetrisathlon", "testexetrisathlon.csproj", "{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x86.ActiveCfg = Debug|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x86.Build.0 = Debug|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x86.ActiveCfg = Release|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x86.Build.0 = Release|x86
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|Any CPU.Build.0 = Release|Any CPU
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x64.ActiveCfg = Debug|x64
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Debug|x64.Build.0 = Debug|x64
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x64.ActiveCfg = Release|x64
{6B0BD176-D6E3-49F5-8CA1-AE5F1535AC59}.Release|x64.Build.0 = Release|x64
EndGlobalSection
EndGlobal