mirror of
https://github.com/Steffo99/better-tee.git
synced 2024-11-24 00:04:19 +00:00
???
This commit is contained in:
parent
8bd953ddfa
commit
40a7c5c6f8
81 changed files with 1333 additions and 1040 deletions
|
@ -1,88 +0,0 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
public abstract class ActController : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
public ActSettings settings = null;
|
||||
protected ActPhase phase = ActPhase.NONE;
|
||||
|
||||
[Header("Results")]
|
||||
public ActResults results = null;
|
||||
|
||||
[Header("Objects")]
|
||||
public Canvas canvas = null;
|
||||
public EventSystem eventSystem = null;
|
||||
|
||||
[Serializable]
|
||||
public class InvalidPhaseException : Exception {
|
||||
public readonly ActPhase currentPhase;
|
||||
|
||||
public InvalidPhaseException(ActPhase currentPhase) {
|
||||
this.currentPhase = currentPhase;
|
||||
}
|
||||
};
|
||||
|
||||
[Serializable]
|
||||
public class MissingSettingsException : Exception {};
|
||||
|
||||
public ActPhase Phase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Call this to initialize the Act (GameObjects, ActSettings, etc). All interactable components should be disabled in this phase.
|
||||
/// </summary>
|
||||
public virtual void ActInit() {
|
||||
phase = ActPhase.INIT;
|
||||
|
||||
canvas = GameObject.FindGameObjectWithTag("Canvas")?.GetComponent<Canvas>();
|
||||
eventSystem = GameObject.FindGameObjectWithTag("EventSystem")?.GetComponent<EventSystem>();
|
||||
|
||||
if(settings == null) {
|
||||
throw new MissingSettingsException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to enable all interactable components in the Act. It should be called when the player is ready to play.
|
||||
/// </summary>
|
||||
public virtual void ActStart() {
|
||||
if(Phase != ActPhase.INIT) throw new InvalidPhaseException(phase);
|
||||
phase = ActPhase.START;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to disable once again all interactable components in the Act. It should be called when the Act is finished (time ran out, player reached submission limit, etc).
|
||||
/// </summary>
|
||||
public virtual void ActEnd() {
|
||||
if(Phase != ActPhase.START) throw new InvalidPhaseException(phase);
|
||||
phase = ActPhase.END;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to cleanup all GameObjects created during the Init phase.
|
||||
/// </summary>
|
||||
public virtual void ActCleanup() {
|
||||
if(Phase != ActPhase.END) {
|
||||
Debug.LogWarningFormat("ActCleanup() was called during {0}", Phase);
|
||||
}
|
||||
phase = ActPhase.CLEANUP;
|
||||
}
|
||||
|
||||
protected virtual void Awake() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Start() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Update() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy() {
|
||||
ActCleanup();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c059168d0dc57204b9d45701d0fc25a0
|
||||
TextScriptImporter:
|
||||
guid: c1b50fe5123a21e44ac5f1d6f24daef2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
22
Assets/Code/Common/ConnectedPlayer.cs
Normal file
22
Assets/Code/Common/ConnectedPlayer.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class ConnectedPlayerData {
|
||||
public string name;
|
||||
public int id;
|
||||
}
|
||||
|
||||
public class ConnectedPlayer {
|
||||
public string name;
|
||||
public int id;
|
||||
|
||||
public ConnectedPlayerData Data {
|
||||
get {
|
||||
return new ConnectedPlayerData {
|
||||
name = this.name,
|
||||
id = this.id
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
14
Assets/Code/Common/DrawingSettings.cs
Normal file
14
Assets/Code/Common/DrawingSettings.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class DrawingSettings : ActSettings {
|
||||
public Color startingColor = Color.white;
|
||||
public Color[] palette = null;
|
||||
public float timeLimit = 99f;
|
||||
public string actName = "Untitled";
|
||||
public string actDescription = "This Act is missing a description.";
|
||||
public string destinationPool = "default";
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
using System;
|
||||
|
||||
[Serializable]
|
||||
public enum GamePhase {
|
||||
UNINTIALIZED,
|
||||
LOBBY,
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
[Serializable]
|
65
Assets/Code/Common/NetMessage.cs
Normal file
65
Assets/Code/Common/NetMessage.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using Mirror;
|
||||
|
||||
|
||||
namespace BetterTee.NetMsg
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
namespace Error {
|
||||
public class InvalidPassword : MessageBase {}
|
||||
public class GameAlreadyStarted : MessageBase {}
|
||||
}
|
||||
|
||||
public class LobbyStatusChange : MessageBase {
|
||||
public ConnectedPlayerData[] players;
|
||||
public ConnectedViewerData[] viewers;
|
||||
}
|
||||
|
||||
public class LobbyEnd : MessageBase
|
||||
{
|
||||
public ConnectedPlayerData[] players;
|
||||
}
|
||||
|
||||
public class ActInit : MessageBase
|
||||
{
|
||||
public ActSettings settings;
|
||||
}
|
||||
|
||||
public class ActStart : MessageBase {}
|
||||
|
||||
public class ActEnd : MessageBase {}
|
||||
|
||||
public class GameEnd : MessageBase
|
||||
{
|
||||
public ConnectedPlayerData[] leaderboard;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Client
|
||||
{
|
||||
public class PlayerJoin : MessageBase
|
||||
{
|
||||
public string playerName;
|
||||
public string gamePassword;
|
||||
}
|
||||
|
||||
public class ActResults : MessageBase
|
||||
{
|
||||
public ActResults results;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Viewer
|
||||
{
|
||||
public class ViewerLink : MessageBase
|
||||
{
|
||||
public string viewerName;
|
||||
public string gamePassword;
|
||||
}
|
||||
|
||||
public class Settings : MessageBase
|
||||
{
|
||||
public GameSettings settings;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
[Serializable]
|
10
Assets/Code/Common/TypingSettings.cs
Normal file
10
Assets/Code/Common/TypingSettings.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class TypingSettings : ActSettings {
|
||||
public float timeLimit = 99f;
|
||||
public string actName = "Untitled";
|
||||
public string actDescription = "This Act is missing a description.";
|
||||
public string destinationPool = "default";
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DrawTool : MonoBehaviour
|
||||
{
|
||||
protected DrawableFrame frame;
|
||||
|
||||
protected virtual void Start() {
|
||||
frame = GetComponent<DrawableFrame>();
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
using UnityEngine;
|
||||
|
||||
|
||||
public class DrawableFrame : MonoBehaviour
|
||||
{
|
||||
[Header("Configuration")]
|
||||
public Vector2Int resolution;
|
||||
public Color startingColor = Color.white;
|
||||
|
||||
[Header("State")]
|
||||
public bool interactable = false;
|
||||
public bool hasChanged = false;
|
||||
|
||||
[Header("References")]
|
||||
protected Texture2D texture = null;
|
||||
protected Sprite sprite = null;
|
||||
protected SpriteRenderer spriteRenderer;
|
||||
|
||||
public Rect Bounds {
|
||||
get {
|
||||
return new Rect(transform.position.x - (transform.localScale.x / 2),
|
||||
transform.position.y - (transform.localScale.y / 2),
|
||||
transform.localScale.x,
|
||||
transform.localScale.y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
texture = new Texture2D(resolution.x, resolution.y);
|
||||
if(resolution.x <= 128 || resolution.y <= 128) {
|
||||
texture.filterMode = FilterMode.Point;
|
||||
}
|
||||
else {
|
||||
texture.filterMode = FilterMode.Trilinear;
|
||||
}
|
||||
|
||||
Color[] colors = texture.GetPixels();
|
||||
for(int i = 0; i < colors.Length; i++) {
|
||||
colors[i] = startingColor;
|
||||
}
|
||||
texture.SetPixels(colors);
|
||||
texture.Apply();
|
||||
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
sprite = Sprite.Create(texture, new Rect(0, 0, resolution.x, resolution.y), new Vector2(0.5f, 0.5f), resolution.x);
|
||||
spriteRenderer.sprite = sprite;
|
||||
}
|
||||
|
||||
public Color[] GetPixels() {
|
||||
return texture.GetPixels();
|
||||
}
|
||||
|
||||
public void SetPixels(Color[] colors) {
|
||||
if(interactable) {
|
||||
texture.SetPixels(colors);
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ToPNG() {
|
||||
return texture.EncodeToPNG();
|
||||
}
|
||||
|
||||
protected void Update() {
|
||||
if(hasChanged) {
|
||||
texture.Apply();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.DrawWireCube(transform.position, transform.localScale);
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
||||
public class DrawingController : ActController
|
||||
{
|
||||
[Header("Prefabs")]
|
||||
public GameObject drawableFramePrefab;
|
||||
public GameObject paletteButtonPrefab;
|
||||
public GameObject radiusSliderPrefab;
|
||||
public GameObject actNamePrefab;
|
||||
public GameObject actDescriptionPrefab;
|
||||
public GameObject actTimerPrefab;
|
||||
|
||||
[Header("Objects")]
|
||||
protected PencilTool pencil;
|
||||
protected DrawableFrame drawableFrame;
|
||||
protected List<PaletteButton> paletteButtons;
|
||||
protected RadiusSlider radiusSlider;
|
||||
protected Text actName;
|
||||
protected Text actDescription;
|
||||
protected Timer actTimer;
|
||||
|
||||
public override void ActInit() {
|
||||
base.ActInit();
|
||||
|
||||
//Load settings
|
||||
DrawingSettings drawingSettings = settings as DrawingSettings;
|
||||
|
||||
//Create drawable frame
|
||||
drawableFrame = Instantiate(drawableFramePrefab, transform).GetComponent<DrawableFrame>();
|
||||
drawableFrame.startingColor = drawingSettings.startingColor;
|
||||
|
||||
//Init PencilTool
|
||||
pencil = drawableFrame.GetComponent<PencilTool>();
|
||||
try {
|
||||
pencil.selectedColor = drawingSettings.palette[0];
|
||||
} catch(ArgumentOutOfRangeException) {
|
||||
pencil.selectedColor = drawingSettings.startingColor;
|
||||
}
|
||||
|
||||
//Init PaletteButtons
|
||||
paletteButtons = new List<PaletteButton>();
|
||||
for(int i = 0; i < drawingSettings.palette.Length; i++) {
|
||||
PaletteButton button = Instantiate(paletteButtonPrefab, canvas.transform).GetComponent<PaletteButton>();
|
||||
RectTransform btnTransform = button.GetComponent<RectTransform>();
|
||||
Image btnImage = button.GetComponent<Image>();
|
||||
button.pencil = pencil;
|
||||
btnImage.color = drawingSettings.palette[i];
|
||||
btnTransform.anchoredPosition = new Vector2(-420 + i * 110, 150);
|
||||
paletteButtons.Add(button);
|
||||
}
|
||||
|
||||
//Init RadiusSlider
|
||||
radiusSlider = Instantiate(radiusSliderPrefab, canvas.transform).GetComponent<RadiusSlider>();
|
||||
radiusSlider.pencil = pencil;
|
||||
|
||||
//Init actName Text
|
||||
actName = Instantiate(actNamePrefab, canvas.transform).GetComponent<Text>();
|
||||
actName.text = drawingSettings.actName;
|
||||
|
||||
//Init actDescription Text
|
||||
actDescription = Instantiate(actDescriptionPrefab, canvas.transform).GetComponent<Text>();
|
||||
actDescription.text = drawingSettings.actDescription;
|
||||
|
||||
//Init actTimer
|
||||
actTimer = Instantiate(actTimerPrefab, canvas.transform).GetComponent<Timer>();
|
||||
actTimer.TimerSet(drawingSettings.timeLimit);
|
||||
}
|
||||
|
||||
public override void ActStart() {
|
||||
base.ActStart();
|
||||
|
||||
//Unlock frame
|
||||
drawableFrame.interactable = false;
|
||||
|
||||
//Start timer
|
||||
actTimer.OnTimeOut += new Action(ActEnd);
|
||||
actTimer.TimerStart();
|
||||
}
|
||||
|
||||
public override void ActEnd() {
|
||||
base.ActEnd();
|
||||
|
||||
//Lock frame
|
||||
drawableFrame.interactable = true;
|
||||
|
||||
//Generate results
|
||||
results = new DrawingResults(drawableFrame.ToPNG());
|
||||
}
|
||||
|
||||
public override void ActCleanup() {
|
||||
base.ActCleanup();
|
||||
|
||||
Destroy(drawableFrame.gameObject);
|
||||
foreach(PaletteButton button in paletteButtons) {
|
||||
Destroy(button.gameObject);
|
||||
}
|
||||
Destroy(radiusSlider.gameObject);
|
||||
Destroy(actName.gameObject);
|
||||
Destroy(actDescription.gameObject);
|
||||
Destroy(actTimer.gameObject);
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class DrawingSettings : ActSettings {
|
||||
public Color startingColor = Color.white;
|
||||
public Color[] palette = null;
|
||||
public float timeLimit = 99f;
|
||||
public string actName = "Untitled";
|
||||
public string actDescription = "This Act is missing a description.";
|
||||
public string destinationPool = "default";
|
||||
|
||||
public DrawingSettings(Color startingColor, Color[] palette, float timeLimit, string actName, string actDescription, string destinationPool) {
|
||||
this.type = "Drawing";
|
||||
this.startingColor = startingColor;
|
||||
this.palette = palette;
|
||||
this.timeLimit = timeLimit;
|
||||
this.actName = actName;
|
||||
this.actDescription = actDescription;
|
||||
this.destinationPool = destinationPool;
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
using Mirror;
|
||||
|
||||
|
||||
namespace NetMessage
|
||||
{
|
||||
namespace Error
|
||||
{
|
||||
public class InvalidPassword : MessageBase {}
|
||||
}
|
||||
|
||||
namespace Connect
|
||||
{
|
||||
public class PlayerJoin : MessageBase
|
||||
{
|
||||
public string playerName;
|
||||
public string gamePassword;
|
||||
}
|
||||
|
||||
public class PlayerJoinSuccessful : MessageBase
|
||||
{
|
||||
public Player player;
|
||||
}
|
||||
|
||||
public class ViewerLink : MessageBase
|
||||
{
|
||||
public string gamePassword;
|
||||
}
|
||||
|
||||
public class ViewerLinkSuccessful : MessageBase
|
||||
{
|
||||
public Viewer viewer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class Settings : MessageBase
|
||||
{
|
||||
public GameSettings settings;
|
||||
}
|
||||
|
||||
public class Start : MessageBase
|
||||
{
|
||||
public Player[] players;
|
||||
}
|
||||
|
||||
public class End : MessageBase
|
||||
{
|
||||
public Player[] leaderboard;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Act
|
||||
{
|
||||
public class Init : MessageBase
|
||||
{
|
||||
public ActSettings settings;
|
||||
}
|
||||
|
||||
public class Start : MessageBase {}
|
||||
|
||||
public class Results : MessageBase
|
||||
{
|
||||
public ActResults results;
|
||||
}
|
||||
|
||||
public class End : MessageBase {}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class PaletteButton : MonoBehaviour
|
||||
{
|
||||
public PencilTool pencil;
|
||||
|
||||
protected Image image;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
image = GetComponent<Image>();
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
pencil.selectedColor = image.color;
|
||||
}
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PencilTool : DrawTool
|
||||
{
|
||||
public Color selectedColor = Color.black;
|
||||
public float size = 1f;
|
||||
|
||||
protected Color[] colors;
|
||||
|
||||
private Vector2Int? previousPixel;
|
||||
private Vector2Int? pixel;
|
||||
|
||||
protected Vector2Int? GetPixelAtScreenPosition(Vector2 screenPosition) {
|
||||
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(screenPosition);
|
||||
if(frame.Bounds.Contains(worldPoint)) {
|
||||
Vector2 normalized = Rect.PointToNormalized(frame.Bounds, worldPoint);
|
||||
Vector2Int result = new Vector2Int(Mathf.FloorToInt(normalized.x * frame.resolution.x), Mathf.FloorToInt(normalized.y * frame.resolution.y));
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void Start() {
|
||||
base.Start();
|
||||
colors = frame.GetPixels();
|
||||
|
||||
Input.simulateMouseWithTouches = false;
|
||||
}
|
||||
|
||||
protected void Update() {
|
||||
bool hasChanged = false;
|
||||
|
||||
// Touch
|
||||
foreach(Touch t in Input.touches) {
|
||||
pixel = GetPixelAtScreenPosition(t.position);
|
||||
previousPixel = GetPixelAtScreenPosition(t.position - t.deltaPosition);
|
||||
if(pixel.HasValue) {
|
||||
if(previousPixel.HasValue) {
|
||||
DrawBresenhamsThickLine(pixel.Value, previousPixel.Value, size, selectedColor);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(pixel.Value, size, selectedColor);
|
||||
}
|
||||
}
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
// Mouse
|
||||
previousPixel = pixel;
|
||||
if(Input.GetMouseButton(0)) {
|
||||
pixel = GetPixelAtScreenPosition(Input.mousePosition);
|
||||
if(pixel.HasValue) {
|
||||
if(previousPixel.HasValue) {
|
||||
DrawBresenhamsThickLine(previousPixel.Value, pixel.Value, size, selectedColor);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(pixel.Value, size, selectedColor);
|
||||
}
|
||||
}
|
||||
hasChanged = true;
|
||||
}
|
||||
else {
|
||||
pixel = null;
|
||||
}
|
||||
|
||||
if(hasChanged) {
|
||||
frame.SetPixels(colors);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawPixel(int x, int y, Color color) {
|
||||
if(x < 0 || x >= frame.resolution.x || y < 0 || y >= frame.resolution.y) return;
|
||||
colors[x + y*frame.resolution.x] = color;
|
||||
}
|
||||
|
||||
protected void DrawCircleEightPoints(Vector2Int center, int x_radius, int y_radius, Color color) {
|
||||
DrawPixel(center.x+x_radius, center.y+y_radius, color);
|
||||
DrawPixel(center.x-x_radius, center.y+y_radius, color);
|
||||
DrawPixel(center.x+x_radius, center.y-y_radius, color);
|
||||
DrawPixel(center.x-x_radius, center.y-y_radius, color);
|
||||
DrawPixel(center.x+y_radius, center.y+x_radius, color);
|
||||
DrawPixel(center.x-y_radius, center.y+x_radius, color);
|
||||
DrawPixel(center.x+y_radius, center.y-x_radius, color);
|
||||
DrawPixel(center.x-y_radius, center.y-x_radius, color);
|
||||
}
|
||||
|
||||
// No idea on how does it work
|
||||
// https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/
|
||||
protected void DrawBresenhamEmptyCircle(Vector2Int center, int radius, Color color) {
|
||||
int x = 0;
|
||||
int y = radius;
|
||||
int d = 3 - 2 * radius;
|
||||
DrawCircleEightPoints(center, x, y, color);
|
||||
while(y >= x) {
|
||||
x++;
|
||||
if(d > 0) {
|
||||
y--;
|
||||
d = d + 4 * (x - y) + 10;
|
||||
}
|
||||
else {
|
||||
d = d + 4 * x + 6;
|
||||
}
|
||||
DrawCircleEightPoints(center, x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawFilledCircle(Vector2Int center, float radius, Color color) {
|
||||
int x_start = Mathf.CeilToInt((float)center.x - radius);
|
||||
int x_end = Mathf.CeilToInt((float)center.x + radius);
|
||||
int y_start = Mathf.CeilToInt((float)center.y - radius);
|
||||
int y_end = Mathf.CeilToInt((float)center.y + radius);
|
||||
for(int x = x_start; x < x_end; x++) {
|
||||
for(int y = y_start; y < y_end; y++) {
|
||||
if(Vector2Int.Distance(new Vector2Int(x, y), center) < radius) {
|
||||
DrawPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm
|
||||
protected void DrawBresenhamsThickLine(Vector2Int start, Vector2Int end, float radius, Color color) {
|
||||
int start_x = start.x, start_y = start.y, end_x = end.x, end_y = end.y;
|
||||
bool steep = Mathf.Abs(end_y - start_y) > Mathf.Abs(end_x - start_x);
|
||||
if (steep) {
|
||||
Utils.Swap<int>(ref start_x, ref start_y);
|
||||
Utils.Swap<int>(ref end_x, ref end_y);
|
||||
}
|
||||
if (start_x > end_x) {
|
||||
Utils.Swap<int>(ref start_x, ref end_x);
|
||||
Utils.Swap<int>(ref start_y, ref end_y);
|
||||
}
|
||||
int dX = (end_x - start_x), dY = Mathf.Abs(end_y - start_y), err = (dX / 2), ystep = (start_y < end_y ? 1 : -1), y = start_y;
|
||||
|
||||
for (int x = start_x; x <= end_x; ++x)
|
||||
{
|
||||
if(steep) {
|
||||
DrawFilledCircle(new Vector2Int(y, x), radius, color);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(new Vector2Int(x, y), radius, color);
|
||||
}
|
||||
err = err - dY;
|
||||
if (err < 0) { y += ystep; err += dX; }
|
||||
}
|
||||
}
|
||||
|
||||
protected void Apply() {
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
using System;
|
||||
|
||||
[Serializable]
|
||||
public struct Player {
|
||||
public string name;
|
||||
public int id;
|
||||
}
|
8
Assets/Code/Player.meta
Normal file
8
Assets/Code/Player.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 38dcaa329b85fc447b2976e3c6d8fcd9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
93
Assets/Code/Player/ActController.cs
Normal file
93
Assets/Code/Player/ActController.cs
Normal file
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public abstract class ActController : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
public ActSettings settings = null;
|
||||
protected ActPhase phase = ActPhase.NONE;
|
||||
|
||||
[Header("Results")]
|
||||
public ActResults results = null;
|
||||
|
||||
[Header("Objects")]
|
||||
public Canvas canvas = null;
|
||||
public EventSystem eventSystem = null;
|
||||
|
||||
[Serializable]
|
||||
public class InvalidPhaseException : Exception {
|
||||
public readonly ActPhase currentPhase;
|
||||
|
||||
public InvalidPhaseException(ActPhase currentPhase) {
|
||||
this.currentPhase = currentPhase;
|
||||
}
|
||||
};
|
||||
|
||||
[Serializable]
|
||||
public class MissingSettingsException : Exception {};
|
||||
|
||||
public ActPhase Phase { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Call this to initialize the Act (GameObjects, ActSettings, etc). All interactable components should be disabled in this phase.
|
||||
/// </summary>
|
||||
public virtual void ActInit() {
|
||||
phase = ActPhase.INIT;
|
||||
|
||||
canvas = GameObject.FindGameObjectWithTag("Canvas")?.GetComponent<Canvas>();
|
||||
eventSystem = GameObject.FindGameObjectWithTag("EventSystem")?.GetComponent<EventSystem>();
|
||||
|
||||
if(settings == null) {
|
||||
throw new MissingSettingsException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to enable all interactable components in the Act. It should be called when the player is ready to play.
|
||||
/// </summary>
|
||||
public virtual void ActStart() {
|
||||
if(Phase != ActPhase.INIT) throw new InvalidPhaseException(phase);
|
||||
phase = ActPhase.START;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to disable once again all interactable components in the Act. It should be called when the Act is finished (time ran out, player reached submission limit, etc).
|
||||
/// </summary>
|
||||
public virtual void ActEnd() {
|
||||
if(Phase != ActPhase.START) throw new InvalidPhaseException(phase);
|
||||
phase = ActPhase.END;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to cleanup all GameObjects created during the Init phase.
|
||||
/// </summary>
|
||||
public virtual void ActCleanup() {
|
||||
if(Phase != ActPhase.END) {
|
||||
Debug.LogWarningFormat("ActCleanup() was called during {0}", Phase);
|
||||
}
|
||||
phase = ActPhase.CLEANUP;
|
||||
}
|
||||
|
||||
protected virtual void Awake() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Start() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Update() {
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy() {
|
||||
ActCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1b7c9976c1c705342bf5b92905a0533e
|
||||
guid: 0f4726b47423bf742bfc526e428363d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
16
Assets/Code/Player/DrawTool.cs
Normal file
16
Assets/Code/Player/DrawTool.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class DrawTool : MonoBehaviour
|
||||
{
|
||||
protected DrawableFrame frame;
|
||||
|
||||
protected virtual void Start() {
|
||||
frame = GetComponent<DrawableFrame>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
80
Assets/Code/Player/DrawableFrame.cs
Normal file
80
Assets/Code/Player/DrawableFrame.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
using UnityEngine;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class DrawableFrame : MonoBehaviour
|
||||
{
|
||||
[Header("Configuration")]
|
||||
public Vector2Int resolution;
|
||||
public Color startingColor = Color.white;
|
||||
|
||||
[Header("State")]
|
||||
public bool interactable = false;
|
||||
public bool hasChanged = false;
|
||||
|
||||
[Header("References")]
|
||||
protected Texture2D texture = null;
|
||||
protected Sprite sprite = null;
|
||||
protected SpriteRenderer spriteRenderer;
|
||||
|
||||
public Rect Bounds {
|
||||
get {
|
||||
return new Rect(transform.position.x - (transform.localScale.x / 2),
|
||||
transform.position.y - (transform.localScale.y / 2),
|
||||
transform.localScale.x,
|
||||
transform.localScale.y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
texture = new Texture2D(resolution.x, resolution.y);
|
||||
if(resolution.x <= 128 || resolution.y <= 128) {
|
||||
texture.filterMode = FilterMode.Point;
|
||||
}
|
||||
else {
|
||||
texture.filterMode = FilterMode.Trilinear;
|
||||
}
|
||||
|
||||
Color[] colors = texture.GetPixels();
|
||||
for(int i = 0; i < colors.Length; i++) {
|
||||
colors[i] = startingColor;
|
||||
}
|
||||
texture.SetPixels(colors);
|
||||
texture.Apply();
|
||||
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
sprite = Sprite.Create(texture, new Rect(0, 0, resolution.x, resolution.y), new Vector2(0.5f, 0.5f), resolution.x);
|
||||
spriteRenderer.sprite = sprite;
|
||||
}
|
||||
|
||||
public Color[] GetPixels() {
|
||||
return texture.GetPixels();
|
||||
}
|
||||
|
||||
public void SetPixels(Color[] colors) {
|
||||
if(interactable) {
|
||||
texture.SetPixels(colors);
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ToPNG() {
|
||||
return texture.EncodeToPNG();
|
||||
}
|
||||
|
||||
protected void Update() {
|
||||
if(hasChanged) {
|
||||
texture.Apply();
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnDrawGizmos()
|
||||
{
|
||||
Gizmos.DrawWireCube(transform.position, transform.localScale);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
111
Assets/Code/Player/DrawingController.cs
Normal file
111
Assets/Code/Player/DrawingController.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class DrawingController : ActController
|
||||
{
|
||||
[Header("Prefabs")]
|
||||
public GameObject drawableFramePrefab;
|
||||
public GameObject paletteButtonPrefab;
|
||||
public GameObject radiusSliderPrefab;
|
||||
public GameObject actNamePrefab;
|
||||
public GameObject actDescriptionPrefab;
|
||||
public GameObject actTimerPrefab;
|
||||
|
||||
[Header("Objects")]
|
||||
protected PencilTool pencil;
|
||||
protected DrawableFrame drawableFrame;
|
||||
protected List<PaletteButton> paletteButtons;
|
||||
protected RadiusSlider radiusSlider;
|
||||
protected Text actName;
|
||||
protected Text actDescription;
|
||||
protected Timer actTimer;
|
||||
|
||||
public override void ActInit() {
|
||||
base.ActInit();
|
||||
|
||||
//Load settings
|
||||
DrawingSettings drawingSettings = settings as DrawingSettings;
|
||||
|
||||
//Create drawable frame
|
||||
drawableFrame = Instantiate(drawableFramePrefab, transform).GetComponent<DrawableFrame>();
|
||||
drawableFrame.startingColor = drawingSettings.startingColor;
|
||||
|
||||
//Init PencilTool
|
||||
pencil = drawableFrame.GetComponent<PencilTool>();
|
||||
try {
|
||||
pencil.selectedColor = drawingSettings.palette[0];
|
||||
} catch(ArgumentOutOfRangeException) {
|
||||
pencil.selectedColor = drawingSettings.startingColor;
|
||||
}
|
||||
|
||||
//Init PaletteButtons
|
||||
paletteButtons = new List<PaletteButton>();
|
||||
for(int i = 0; i < drawingSettings.palette.Length; i++) {
|
||||
PaletteButton button = Instantiate(paletteButtonPrefab, canvas.transform).GetComponent<PaletteButton>();
|
||||
RectTransform btnTransform = button.GetComponent<RectTransform>();
|
||||
Image btnImage = button.GetComponent<Image>();
|
||||
button.pencil = pencil;
|
||||
btnImage.color = drawingSettings.palette[i];
|
||||
btnTransform.anchoredPosition = new Vector2(-420 + i * 110, 150);
|
||||
paletteButtons.Add(button);
|
||||
}
|
||||
|
||||
//Init RadiusSlider
|
||||
radiusSlider = Instantiate(radiusSliderPrefab, canvas.transform).GetComponent<RadiusSlider>();
|
||||
radiusSlider.pencil = pencil;
|
||||
|
||||
//Init actName Text
|
||||
actName = Instantiate(actNamePrefab, canvas.transform).GetComponent<Text>();
|
||||
actName.text = drawingSettings.actName;
|
||||
|
||||
//Init actDescription Text
|
||||
actDescription = Instantiate(actDescriptionPrefab, canvas.transform).GetComponent<Text>();
|
||||
actDescription.text = drawingSettings.actDescription;
|
||||
|
||||
//Init actTimer
|
||||
actTimer = Instantiate(actTimerPrefab, canvas.transform).GetComponent<Timer>();
|
||||
actTimer.TimerSet(drawingSettings.timeLimit);
|
||||
}
|
||||
|
||||
public override void ActStart() {
|
||||
base.ActStart();
|
||||
|
||||
//Unlock frame
|
||||
drawableFrame.interactable = false;
|
||||
|
||||
//Start timer
|
||||
actTimer.OnTimeOut += new Action(ActEnd);
|
||||
actTimer.TimerStart();
|
||||
}
|
||||
|
||||
public override void ActEnd() {
|
||||
base.ActEnd();
|
||||
|
||||
//Lock frame
|
||||
drawableFrame.interactable = true;
|
||||
|
||||
//Generate results
|
||||
results = new DrawingResults(drawableFrame.ToPNG());
|
||||
}
|
||||
|
||||
public override void ActCleanup() {
|
||||
base.ActCleanup();
|
||||
|
||||
Destroy(drawableFrame.gameObject);
|
||||
foreach(PaletteButton button in paletteButtons) {
|
||||
Destroy(button.gameObject);
|
||||
}
|
||||
Destroy(radiusSlider.gameObject);
|
||||
Destroy(actName.gameObject);
|
||||
Destroy(actDescription.gameObject);
|
||||
Destroy(actTimer.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
Assets/Code/Player/PaletteButton.cs
Normal file
25
Assets/Code/Player/PaletteButton.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BetterTee.Player {
|
||||
|
||||
public class PaletteButton : MonoBehaviour
|
||||
{
|
||||
public PencilTool pencil;
|
||||
|
||||
protected Image image;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
image = GetComponent<Image>();
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
pencil.selectedColor = image.color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
158
Assets/Code/Player/PencilTool.cs
Normal file
158
Assets/Code/Player/PencilTool.cs
Normal file
|
@ -0,0 +1,158 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class PencilTool : DrawTool
|
||||
{
|
||||
public Color selectedColor = Color.black;
|
||||
public float size = 1f;
|
||||
|
||||
protected Color[] colors;
|
||||
|
||||
private Vector2Int? previousPixel;
|
||||
private Vector2Int? pixel;
|
||||
|
||||
protected Vector2Int? GetPixelAtScreenPosition(Vector2 screenPosition) {
|
||||
Vector2 worldPoint = Camera.main.ScreenToWorldPoint(screenPosition);
|
||||
if(frame.Bounds.Contains(worldPoint)) {
|
||||
Vector2 normalized = Rect.PointToNormalized(frame.Bounds, worldPoint);
|
||||
Vector2Int result = new Vector2Int(Mathf.FloorToInt(normalized.x * frame.resolution.x), Mathf.FloorToInt(normalized.y * frame.resolution.y));
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void Start() {
|
||||
base.Start();
|
||||
colors = frame.GetPixels();
|
||||
|
||||
Input.simulateMouseWithTouches = false;
|
||||
}
|
||||
|
||||
protected void Update() {
|
||||
bool hasChanged = false;
|
||||
|
||||
// Touch
|
||||
foreach(Touch t in Input.touches) {
|
||||
pixel = GetPixelAtScreenPosition(t.position);
|
||||
previousPixel = GetPixelAtScreenPosition(t.position - t.deltaPosition);
|
||||
if(pixel.HasValue) {
|
||||
if(previousPixel.HasValue) {
|
||||
DrawBresenhamsThickLine(pixel.Value, previousPixel.Value, size, selectedColor);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(pixel.Value, size, selectedColor);
|
||||
}
|
||||
}
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
// Mouse
|
||||
previousPixel = pixel;
|
||||
if(Input.GetMouseButton(0)) {
|
||||
pixel = GetPixelAtScreenPosition(Input.mousePosition);
|
||||
if(pixel.HasValue) {
|
||||
if(previousPixel.HasValue) {
|
||||
DrawBresenhamsThickLine(previousPixel.Value, pixel.Value, size, selectedColor);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(pixel.Value, size, selectedColor);
|
||||
}
|
||||
}
|
||||
hasChanged = true;
|
||||
}
|
||||
else {
|
||||
pixel = null;
|
||||
}
|
||||
|
||||
if(hasChanged) {
|
||||
frame.SetPixels(colors);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawPixel(int x, int y, Color color) {
|
||||
if(x < 0 || x >= frame.resolution.x || y < 0 || y >= frame.resolution.y) return;
|
||||
colors[x + y*frame.resolution.x] = color;
|
||||
}
|
||||
|
||||
protected void DrawCircleEightPoints(Vector2Int center, int x_radius, int y_radius, Color color) {
|
||||
DrawPixel(center.x+x_radius, center.y+y_radius, color);
|
||||
DrawPixel(center.x-x_radius, center.y+y_radius, color);
|
||||
DrawPixel(center.x+x_radius, center.y-y_radius, color);
|
||||
DrawPixel(center.x-x_radius, center.y-y_radius, color);
|
||||
DrawPixel(center.x+y_radius, center.y+x_radius, color);
|
||||
DrawPixel(center.x-y_radius, center.y+x_radius, color);
|
||||
DrawPixel(center.x+y_radius, center.y-x_radius, color);
|
||||
DrawPixel(center.x-y_radius, center.y-x_radius, color);
|
||||
}
|
||||
|
||||
// No idea on how does it work
|
||||
// https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/
|
||||
protected void DrawBresenhamEmptyCircle(Vector2Int center, int radius, Color color) {
|
||||
int x = 0;
|
||||
int y = radius;
|
||||
int d = 3 - 2 * radius;
|
||||
DrawCircleEightPoints(center, x, y, color);
|
||||
while(y >= x) {
|
||||
x++;
|
||||
if(d > 0) {
|
||||
y--;
|
||||
d = d + 4 * (x - y) + 10;
|
||||
}
|
||||
else {
|
||||
d = d + 4 * x + 6;
|
||||
}
|
||||
DrawCircleEightPoints(center, x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawFilledCircle(Vector2Int center, float radius, Color color) {
|
||||
int x_start = Mathf.CeilToInt((float)center.x - radius);
|
||||
int x_end = Mathf.CeilToInt((float)center.x + radius);
|
||||
int y_start = Mathf.CeilToInt((float)center.y - radius);
|
||||
int y_end = Mathf.CeilToInt((float)center.y + radius);
|
||||
for(int x = x_start; x < x_end; x++) {
|
||||
for(int y = y_start; y < y_end; y++) {
|
||||
if(Vector2Int.Distance(new Vector2Int(x, y), center) < radius) {
|
||||
DrawPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm
|
||||
protected void DrawBresenhamsThickLine(Vector2Int start, Vector2Int end, float radius, Color color) {
|
||||
int start_x = start.x, start_y = start.y, end_x = end.x, end_y = end.y;
|
||||
bool steep = Mathf.Abs(end_y - start_y) > Mathf.Abs(end_x - start_x);
|
||||
if (steep) {
|
||||
Utils.Swap<int>(ref start_x, ref start_y);
|
||||
Utils.Swap<int>(ref end_x, ref end_y);
|
||||
}
|
||||
if (start_x > end_x) {
|
||||
Utils.Swap<int>(ref start_x, ref end_x);
|
||||
Utils.Swap<int>(ref start_y, ref end_y);
|
||||
}
|
||||
int dX = (end_x - start_x), dY = Mathf.Abs(end_y - start_y), err = (dX / 2), ystep = (start_y < end_y ? 1 : -1), y = start_y;
|
||||
|
||||
for (int x = start_x; x <= end_x; ++x)
|
||||
{
|
||||
if(steep) {
|
||||
DrawFilledCircle(new Vector2Int(y, x), radius, color);
|
||||
}
|
||||
else {
|
||||
DrawFilledCircle(new Vector2Int(x, y), radius, color);
|
||||
}
|
||||
err = err - dY;
|
||||
if (err < 0) { y += ystep; err += dX; }
|
||||
}
|
||||
}
|
||||
|
||||
protected void Apply() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
99
Assets/Code/Player/PlayerMainController.cs
Normal file
99
Assets/Code/Player/PlayerMainController.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
using BetterTee;
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class PlayerMainController : MonoBehaviour
|
||||
{
|
||||
[Header("WIP")]
|
||||
public string address = "127.0.0.1";
|
||||
public string playerName = "Steffo";
|
||||
public string gamePassword = "ASDF";
|
||||
|
||||
void Start() {
|
||||
ConnectToServer(address, playerName);
|
||||
}
|
||||
|
||||
[Header("Objects")]
|
||||
public ActController currentAct = null;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public GameObject drawingControllerPrefab;
|
||||
public GameObject typingControllerPrefab;
|
||||
|
||||
[Serializable]
|
||||
public class InvalidActTypeException : Exception {
|
||||
public readonly string actType;
|
||||
|
||||
public InvalidActTypeException(string actType) {
|
||||
this.actType = actType;
|
||||
}
|
||||
};
|
||||
|
||||
public void LoadAct(ActSettings settings) {
|
||||
if(settings.type == "Drawing") {
|
||||
currentAct = Instantiate(drawingControllerPrefab, transform).GetComponent<DrawingController>();
|
||||
}
|
||||
else if (settings.type == "Typing") {
|
||||
currentAct = Instantiate(typingControllerPrefab, transform).GetComponent<TypingController>();
|
||||
}
|
||||
else throw new InvalidActTypeException(settings.type);
|
||||
currentAct.settings = settings;
|
||||
}
|
||||
|
||||
public void ConnectToServer(string address, string playerName) {
|
||||
LogFilter.Debug = true;
|
||||
Transport.activeTransport = GetComponent<TelepathyTransport>();
|
||||
NetworkClient.RegisterHandler<ConnectMessage>(OnConnect);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.PlayerJoined>(OnPlayerJoinSuccessful);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.LobbyEnd>(OnLobbyEnd);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.GameEnd>(OnGameEnd);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.ActInit>(OnActInit);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.ActStart>(OnActStart);
|
||||
NetworkClient.RegisterHandler<NetMsg.Server.ActEnd>(OnActEnd);
|
||||
NetworkClient.Connect(address);
|
||||
}
|
||||
|
||||
#region Network Events
|
||||
|
||||
protected void OnConnect(NetworkConnection connection, ConnectMessage message) {
|
||||
Debug.Log("Sending NetMessage.Connect.PlayerJoin");
|
||||
connection.Send<NetMsg.Client.PlayerJoin>(new NetMsg.Client.PlayerJoin {
|
||||
playerName = playerName,
|
||||
gamePassword = gamePassword
|
||||
});
|
||||
}
|
||||
|
||||
protected void OnPlayerJoinSuccessful(NetworkConnection connection, NetMsg.Server.PlayerJoined message) {
|
||||
|
||||
}
|
||||
|
||||
protected void OnLobbyEnd(NetworkConnection connection, NetMsg.Server.LobbyEnd message) {}
|
||||
|
||||
protected void OnGameEnd(NetworkConnection connection, NetMsg.Server.GameEnd message) {}
|
||||
|
||||
protected void OnActInit(NetworkConnection connection, NetMsg.Server.ActInit message) {
|
||||
LoadAct(message.settings);
|
||||
currentAct.ActInit();
|
||||
}
|
||||
|
||||
protected void OnActStart(NetworkConnection connection, NetMsg.Server.ActStart message) {
|
||||
currentAct.ActStart();
|
||||
}
|
||||
|
||||
protected void OnActEnd(NetworkConnection connection, NetMsg.Server.ActEnd message) {
|
||||
currentAct.ActEnd();
|
||||
//SEND RESULTS HERE
|
||||
|
||||
//test this
|
||||
Destroy(currentAct);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
22
Assets/Code/Player/RadiusSlider.cs
Normal file
22
Assets/Code/Player/RadiusSlider.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BetterTee.Player {
|
||||
|
||||
public class RadiusSlider : MonoBehaviour
|
||||
{
|
||||
public PencilTool pencil;
|
||||
|
||||
protected Slider slider;
|
||||
|
||||
protected void Start() {
|
||||
slider = GetComponent<Slider>();
|
||||
}
|
||||
|
||||
public void OnValueChange()
|
||||
{
|
||||
pencil.size = slider.value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
27
Assets/Code/Player/Submit.cs
Normal file
27
Assets/Code/Player/Submit.cs
Normal file
|
@ -0,0 +1,27 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class Submit : MonoBehaviour
|
||||
{
|
||||
public InputField inputField;
|
||||
public TypingController typingController;
|
||||
|
||||
protected EventSystem eventSystem;
|
||||
|
||||
protected void Start() {
|
||||
eventSystem = GameObject.FindGameObjectWithTag("EventSystem").GetComponent<EventSystem>();
|
||||
}
|
||||
|
||||
public void OnClick() {
|
||||
typingController.Submit(inputField.text);
|
||||
inputField.text = "";
|
||||
eventSystem.SetSelectedGameObject(inputField.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
56
Assets/Code/Player/Timer.cs
Normal file
56
Assets/Code/Player/Timer.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class Timer : MonoBehaviour
|
||||
{
|
||||
public float startingTime = 0f;
|
||||
public float time = 0f;
|
||||
|
||||
private bool isTriggered = false;
|
||||
private bool isRunning = false;
|
||||
|
||||
protected void Update() {
|
||||
if(time >= 0f) {
|
||||
if(isRunning) {
|
||||
time -= Time.deltaTime;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(isTriggered) {
|
||||
OnTimeOut();
|
||||
time = 0f;
|
||||
isTriggered = false;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TimerSet(float startingTime) {
|
||||
isTriggered = true;
|
||||
isRunning = false;
|
||||
this.startingTime = startingTime;
|
||||
time = startingTime;
|
||||
}
|
||||
|
||||
public void TimerStart() {
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public void TimerPause() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public void TimerCancel() {
|
||||
time = 0f;
|
||||
isTriggered = false;
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public event Action OnTimeOut;
|
||||
}
|
||||
|
||||
}
|
24
Assets/Code/Player/TimerToText.cs
Normal file
24
Assets/Code/Player/TimerToText.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BetterTee.Player
|
||||
{
|
||||
|
||||
public class TimerToText : MonoBehaviour
|
||||
{
|
||||
protected Timer timer;
|
||||
protected Text text;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
timer = GetComponent<Timer>();
|
||||
text = GetComponent<Text>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
text.text = Mathf.CeilToInt(timer.time).ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
109
Assets/Code/Player/TypingController.cs
Normal file
109
Assets/Code/Player/TypingController.cs
Normal file
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BetterTee.Player {
|
||||
|
||||
public class TypingController : ActController
|
||||
{
|
||||
public List<String> submissions;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public GameObject actNamePrefab;
|
||||
public GameObject actDescriptionPrefab;
|
||||
public GameObject timerPrefab;
|
||||
public GameObject submissionFieldPrefab;
|
||||
public GameObject submitPrefab;
|
||||
public GameObject submittedCountPrefab;
|
||||
|
||||
[Header("Objects")]
|
||||
protected Text actName;
|
||||
protected Text actDescription;
|
||||
protected Timer actTimer;
|
||||
protected InputField submissionField;
|
||||
protected Submit submit;
|
||||
protected Text submittedCount;
|
||||
|
||||
protected override void Start() {
|
||||
base.Start();
|
||||
submissions = new List<string>();
|
||||
}
|
||||
|
||||
public override void ActInit() {
|
||||
base.ActInit();
|
||||
|
||||
//Load settings
|
||||
TypingSettings typingSettings = settings as TypingSettings;
|
||||
|
||||
//Init actName Text
|
||||
actName = Instantiate(actNamePrefab, canvas.transform).GetComponent<Text>();
|
||||
actName.text = typingSettings.actName;
|
||||
|
||||
//Init actDescription Text
|
||||
actDescription = Instantiate(actDescriptionPrefab, canvas.transform).GetComponent<Text>();
|
||||
actDescription.text = typingSettings.actDescription;
|
||||
|
||||
//Init actTimer
|
||||
actTimer = Instantiate(timerPrefab, canvas.transform).GetComponent<Timer>();
|
||||
actTimer.TimerSet(typingSettings.timeLimit);
|
||||
|
||||
//Init submissionInputField
|
||||
submissionField = Instantiate(submissionFieldPrefab, canvas.transform).GetComponent<InputField>();
|
||||
|
||||
//Init submit Button
|
||||
submit = Instantiate(submitPrefab, canvas.transform).GetComponent<Submit>();
|
||||
submit.typingController = this;
|
||||
submit.inputField = submissionField;
|
||||
|
||||
//Init submissionCount Text
|
||||
submittedCount = Instantiate(submittedCountPrefab, canvas.transform).GetComponent<Text>();
|
||||
submittedCount.text = "";
|
||||
}
|
||||
|
||||
public override void ActStart() {
|
||||
base.ActStart();
|
||||
|
||||
//Enable submissionField and submit Button
|
||||
submissionField.interactable = true;
|
||||
submit.GetComponent<Button>().interactable = true;
|
||||
|
||||
//Focus on submissionField
|
||||
eventSystem.SetSelectedGameObject(submissionField.gameObject);
|
||||
|
||||
//Start timer
|
||||
actTimer.OnTimeOut += new Action(ActEnd);
|
||||
actTimer.TimerStart();
|
||||
}
|
||||
|
||||
public override void ActEnd() {
|
||||
base.ActEnd();
|
||||
|
||||
//Disable submissionField and submit Button
|
||||
submissionField.interactable = false;
|
||||
submit.GetComponent<Button>().interactable = false;
|
||||
|
||||
//Create results
|
||||
results = new TypingResults(submissions.ToArray());
|
||||
}
|
||||
|
||||
public override void ActCleanup() {
|
||||
base.ActCleanup();
|
||||
|
||||
Destroy(actName.gameObject);
|
||||
Destroy(actDescription.gameObject);
|
||||
Destroy(actTimer.gameObject);
|
||||
Destroy(submissionField.gameObject);
|
||||
Destroy(submit.gameObject);
|
||||
Destroy(submittedCount.gameObject);
|
||||
}
|
||||
|
||||
public void Submit(string submission) {
|
||||
if(submission != "") {
|
||||
submissions.Add(submission);
|
||||
submittedCount.text = String.Format("Submitted: {0}", submissions.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
|
||||
public class PlayerMainController : MonoBehaviour
|
||||
{
|
||||
[Header("WIP")]
|
||||
public string address = "127.0.0.1";
|
||||
public string playerName = "Steffo";
|
||||
public string gamePassword = "ASDF";
|
||||
|
||||
void Start() {
|
||||
ConnectToServer(address, playerName);
|
||||
}
|
||||
|
||||
[Header("Objects")]
|
||||
public ActController currentAct = null;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public GameObject drawingControllerPrefab;
|
||||
public GameObject typingControllerPrefab;
|
||||
|
||||
[Serializable]
|
||||
public class InvalidActTypeException : Exception {
|
||||
public readonly string actType;
|
||||
|
||||
public InvalidActTypeException(string actType) {
|
||||
this.actType = actType;
|
||||
}
|
||||
};
|
||||
|
||||
public void LoadAct(ActSettings settings) {
|
||||
if(settings.type == "Drawing") {
|
||||
currentAct = Instantiate(drawingControllerPrefab, transform).GetComponent<DrawingController>();
|
||||
}
|
||||
else if (settings.type == "Typing") {
|
||||
currentAct = Instantiate(typingControllerPrefab, transform).GetComponent<TypingController>();
|
||||
}
|
||||
else throw new InvalidActTypeException(settings.type);
|
||||
currentAct.settings = settings;
|
||||
}
|
||||
|
||||
public void ConnectToServer(string address, string playerName) {
|
||||
LogFilter.Debug = true;
|
||||
Transport.activeTransport = GetComponent<TelepathyTransport>();
|
||||
NetworkClient.RegisterHandler<ConnectMessage>(OnConnect);
|
||||
NetworkClient.RegisterHandler<NetMessage.Connect.PlayerJoinSuccessful>(OnPlayerJoinSuccessful);
|
||||
NetworkClient.RegisterHandler<NetMessage.Game.Settings>(OnGameSettings);
|
||||
NetworkClient.RegisterHandler<NetMessage.Game.Start>(OnGameStart);
|
||||
NetworkClient.RegisterHandler<NetMessage.Game.End>(OnGameEnd);
|
||||
NetworkClient.RegisterHandler<NetMessage.Act.Init>(OnActInit);
|
||||
NetworkClient.RegisterHandler<NetMessage.Act.Start>(OnActStart);
|
||||
NetworkClient.RegisterHandler<NetMessage.Act.End>(OnActEnd);
|
||||
NetworkClient.Connect(address);
|
||||
}
|
||||
|
||||
public void OnConnect(NetworkConnection connection, ConnectMessage message) {
|
||||
Debug.Log("Sending NetMessage.Connect.PlayerJoin");
|
||||
NetMessage.Connect.PlayerJoin playerJoin = new NetMessage.Connect.PlayerJoin {
|
||||
playerName = playerName,
|
||||
gamePassword = gamePassword
|
||||
};
|
||||
connection.Send<NetMessage.Connect.PlayerJoin>(playerJoin);
|
||||
}
|
||||
|
||||
protected void OnPlayerJoinSuccessful(NetworkConnection connection, NetMessage.Connect.PlayerJoinSuccessful message) {}
|
||||
|
||||
protected void OnGameSettings(NetworkConnection connection, NetMessage.Game.Settings message) {}
|
||||
|
||||
protected void OnGameStart(NetworkConnection connection, NetMessage.Game.Start message) {}
|
||||
|
||||
protected void OnGameEnd(NetworkConnection connection, NetMessage.Game.End message) {}
|
||||
|
||||
protected void OnActInit(NetworkConnection connection, NetMessage.Act.Init message) {
|
||||
LoadAct(message.settings);
|
||||
currentAct.ActInit();
|
||||
}
|
||||
|
||||
protected void OnActStart(NetworkConnection connection, NetMessage.Act.Start message) {
|
||||
currentAct.ActStart();
|
||||
}
|
||||
|
||||
protected void OnActEnd(NetworkConnection connection, NetMessage.Act.End message) {
|
||||
currentAct.ActEnd();
|
||||
//SEND RESULTS HERE
|
||||
|
||||
//test this
|
||||
Destroy(currentAct);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class RadiusSlider : MonoBehaviour
|
||||
{
|
||||
public PencilTool pencil;
|
||||
|
||||
protected Slider slider;
|
||||
|
||||
protected void Start() {
|
||||
slider = GetComponent<Slider>();
|
||||
}
|
||||
|
||||
public void OnValueChange()
|
||||
{
|
||||
pencil.size = slider.value;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
{
|
||||
"type": "Drawing",
|
||||
"actName": "Sample Drawing Act",
|
||||
"actDescription": "This is a sample act that should be able to be loaded as a DrawingSettings instance.",
|
||||
"timeLimit": 66.6,
|
||||
"startingColor": {
|
||||
"r": 1.0,
|
||||
"g": 1.0,
|
||||
"b": 1.0,
|
||||
"a": 1.0
|
||||
},
|
||||
"palette": [
|
||||
{
|
||||
"r": 1.0,
|
||||
"g": 0.0,
|
||||
"b": 0.0,
|
||||
"a": 1.0
|
||||
},
|
||||
{
|
||||
"r": 1.0,
|
||||
"g": 1.0,
|
||||
"b": 0.0,
|
||||
"a": 1.0
|
||||
},
|
||||
{
|
||||
"r": 0.0,
|
||||
"g": 1.0,
|
||||
"b": 0.0,
|
||||
"a": 1.0
|
||||
},
|
||||
{
|
||||
"r": 0.0,
|
||||
"g": 1.0,
|
||||
"b": 1.0,
|
||||
"a": 1.0
|
||||
},
|
||||
{
|
||||
"r": 0.0,
|
||||
"g": 0.0,
|
||||
"b": 1.0,
|
||||
"a": 1.0
|
||||
},
|
||||
{
|
||||
"r": 1.0,
|
||||
"g": 0.0,
|
||||
"b": 1.0,
|
||||
"a": 1.0
|
||||
}
|
||||
],
|
||||
"destinationPool": "sample"
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"type": "Typing",
|
||||
"actName": "Sample Typing Act",
|
||||
"actDescription": "This is a sample act that should be able to be loaded as a TypingSettings instance.",
|
||||
"timeLimit": 66.6,
|
||||
"destinationPool": "sample"
|
||||
}
|
8
Assets/Code/Server.meta
Normal file
8
Assets/Code/Server.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6653cdd1e604f58418506141bc2215a9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
108
Assets/Code/Server/ServerMainController.cs
Normal file
108
Assets/Code/Server/ServerMainController.cs
Normal file
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
namespace BetterTee.Server {
|
||||
|
||||
public class ServerMainController : MonoBehaviour
|
||||
{
|
||||
[Header("Status")]
|
||||
public string password = null;
|
||||
public List<ConnectedPlayerData> players;
|
||||
public List<ConnectedViewerData> viewers;
|
||||
public GamePhase phase = GamePhase.UNINTIALIZED;
|
||||
|
||||
[Header("Constants")]
|
||||
public const int MAX_CONNECTIONS = 32;
|
||||
|
||||
protected void Start() {
|
||||
StartServer();
|
||||
}
|
||||
|
||||
protected void OnDestroy() {
|
||||
if(NetworkServer.active) NetworkServer.Shutdown();
|
||||
}
|
||||
|
||||
public void StartServer() {
|
||||
LogFilter.Debug = true;
|
||||
phase = GamePhase.LOBBY;
|
||||
Transport.activeTransport = GetComponent<TelepathyTransport>();
|
||||
|
||||
#region Client Messages
|
||||
NetworkServer.RegisterHandler<NetMsg.Client.PlayerJoin>(OnPlayerJoin);
|
||||
NetworkServer.RegisterHandler<NetMsg.Client.ActResults>(OnActResults);
|
||||
#endregion
|
||||
|
||||
#region Viewer Messages
|
||||
NetworkServer.RegisterHandler<NetMsg.Viewer.ViewerLink>(OnViewerLink);
|
||||
#endregion
|
||||
|
||||
#region Other Messages
|
||||
NetworkServer.RegisterHandler<ConnectMessage>(OnConnect);
|
||||
#endregion
|
||||
|
||||
NetworkServer.Listen(MAX_CONNECTIONS);
|
||||
}
|
||||
|
||||
#region Network Events
|
||||
|
||||
protected void OnConnect(NetworkConnection connection, ConnectMessage message) {}
|
||||
|
||||
protected void OnPlayerJoin(NetworkConnection connection, NetMsg.Client.PlayerJoin message)
|
||||
{
|
||||
if(message.gamePassword != password) {
|
||||
connection.Send<NetMsg.Server.Error.InvalidPassword>(new NetMsg.Server.Error.InvalidPassword());
|
||||
connection.Disconnect();
|
||||
return;
|
||||
}
|
||||
if(phase != GamePhase.LOBBY) {
|
||||
connection.Send<NetMsg.Server.Error.GameAlreadyStarted>(new NetMsg.Server.Error.GameAlreadyStarted());
|
||||
connection.Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectedPlayerData newPlayer = new ConnectedPlayerData {
|
||||
name = message.playerName,
|
||||
id = players.Count
|
||||
};
|
||||
players.Add(newPlayer);
|
||||
|
||||
Debug.LogFormat("Player {0} joined the game", message.playerName);
|
||||
|
||||
connection.Send<NetMsg.Server.LobbyStatusChange>(new NetMsg.Server.LobbyStatusChange {
|
||||
players = players.ToArray(),
|
||||
viewers = viewers.ToArray()
|
||||
});
|
||||
}
|
||||
|
||||
protected void OnActResults(NetworkConnection connection, NetMsg.Client.ActResults message) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
protected void OnViewerLink(NetworkConnection connection, NetMsg.Viewer.ViewerLink message)
|
||||
{
|
||||
if(message.gamePassword != password) {
|
||||
connection.Send<NetMsg.Server.Error.InvalidPassword>(new NetMsg.Server.Error.InvalidPassword());
|
||||
connection.Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectedViewerData newViewer = new ConnectedViewerData {
|
||||
id = viewers.Count
|
||||
};
|
||||
viewers.Add(newViewer);
|
||||
|
||||
Debug.LogFormat("Viewer {0} is now linked to the game", message.viewerName);
|
||||
|
||||
connection.Send<NetMsg.Server.LobbyStatusChange>(new NetMsg.Server.LobbyStatusChange {
|
||||
players = players.ToArray(),
|
||||
viewers = viewers.ToArray()
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
public class ServerMainController : MonoBehaviour
|
||||
{
|
||||
[Header("Status")]
|
||||
public string password = null;
|
||||
public List<Player> players;
|
||||
public List<Viewer> viewers;
|
||||
public GamePhase phase = GamePhase.UNINTIALIZED;
|
||||
|
||||
[Header("Constants")]
|
||||
public const int MAX_CONNECTIONS = 32;
|
||||
|
||||
protected void Start() {
|
||||
StartServer();
|
||||
}
|
||||
|
||||
protected void OnDestroy() {
|
||||
if(NetworkServer.active) NetworkServer.Shutdown();
|
||||
}
|
||||
|
||||
public void StartServer() {
|
||||
LogFilter.Debug = true;
|
||||
phase = GamePhase.LOBBY;
|
||||
Transport.activeTransport = GetComponent<TelepathyTransport>();
|
||||
NetworkServer.RegisterHandler<NetMessage.Connect.PlayerJoin>(OnPlayerJoin);
|
||||
NetworkServer.RegisterHandler<NetMessage.Error.InvalidPassword>(OnInvalidPassword);
|
||||
NetworkServer.RegisterHandler<NetMessage.Connect.ViewerLink>(OnViewerLink);
|
||||
NetworkServer.RegisterHandler<NetMessage.Game.Settings>(OnGameSettings);
|
||||
NetworkServer.RegisterHandler<NetMessage.Act.Results>(OnActResults);
|
||||
NetworkServer.Listen(MAX_CONNECTIONS);
|
||||
}
|
||||
|
||||
public void OnPlayerJoin(NetworkConnection connection, NetMessage.Connect.PlayerJoin message) {
|
||||
Debug.LogFormat("Received NetMessage.Connect.PlayerJoin from {0}", message.playerName);
|
||||
if(message.gamePassword != password) {
|
||||
connection.Send<NetMessage.Error.InvalidPassword>(new NetMessage.Error.InvalidPassword());
|
||||
connection.Disconnect();
|
||||
return;
|
||||
}
|
||||
Player newPlayer = new Player {
|
||||
name = message.playerName,
|
||||
id = players.Count
|
||||
};
|
||||
players.Add(newPlayer);
|
||||
|
||||
NetMessage.Connect.PlayerJoinSuccessful reply = new NetMessage.Connect.PlayerJoinSuccessful {
|
||||
player = newPlayer
|
||||
};
|
||||
connection.Send<NetMessage.Connect.PlayerJoinSuccessful>(reply);
|
||||
}
|
||||
|
||||
public void OnInvalidPassword(NetworkConnection connection, NetMessage.Error.InvalidPassword message) {
|
||||
Debug.LogError("Invalid gamePassword");
|
||||
}
|
||||
|
||||
|
||||
public void OnViewerLink(NetworkConnection connection, NetMessage.Connect.ViewerLink message) {
|
||||
if(message.gamePassword != password) {
|
||||
connection.Send<NetMessage.Error.InvalidPassword>(new NetMessage.Error.InvalidPassword());
|
||||
return;
|
||||
}
|
||||
Viewer newViewer = new Viewer {
|
||||
id = viewers.Count
|
||||
};
|
||||
viewers.Add(newViewer);
|
||||
|
||||
NetMessage.Connect.ViewerLinkSuccessful reply = new NetMessage.Connect.ViewerLinkSuccessful {
|
||||
viewer = newViewer
|
||||
};
|
||||
connection.Send<NetMessage.Connect.ViewerLinkSuccessful>(reply);
|
||||
}
|
||||
|
||||
public void OnGameSettings(NetworkConnection connection, NetMessage.Game.Settings message) {}
|
||||
public void OnActResults(NetworkConnection connection, NetMessage.Act.Results message) {}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class Submit : MonoBehaviour
|
||||
{
|
||||
public InputField inputField;
|
||||
public TypingController typingController;
|
||||
|
||||
protected EventSystem eventSystem;
|
||||
|
||||
protected void Start() {
|
||||
eventSystem = GameObject.FindGameObjectWithTag("EventSystem").GetComponent<EventSystem>();
|
||||
}
|
||||
|
||||
public void OnClick() {
|
||||
typingController.Submit(inputField.text);
|
||||
inputField.text = "";
|
||||
eventSystem.SetSelectedGameObject(inputField.gameObject);
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class Timer : MonoBehaviour
|
||||
{
|
||||
public float startingTime = 0f;
|
||||
public float time = 0f;
|
||||
|
||||
private bool isTriggered = false;
|
||||
private bool isRunning = false;
|
||||
|
||||
protected void Update() {
|
||||
if(time >= 0f) {
|
||||
if(isRunning) {
|
||||
time -= Time.deltaTime;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(isTriggered) {
|
||||
OnTimeOut();
|
||||
time = 0f;
|
||||
isTriggered = false;
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TimerSet(float startingTime) {
|
||||
isTriggered = true;
|
||||
isRunning = false;
|
||||
this.startingTime = startingTime;
|
||||
time = startingTime;
|
||||
}
|
||||
|
||||
public void TimerStart() {
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public void TimerPause() {
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public void TimerCancel() {
|
||||
time = 0f;
|
||||
isTriggered = false;
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
public event Action OnTimeOut;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class TimerToText : MonoBehaviour
|
||||
{
|
||||
protected Timer timer;
|
||||
protected Text text;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
timer = GetComponent<Timer>();
|
||||
text = GetComponent<Text>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
text.text = Mathf.CeilToInt(timer.time).ToString();
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
public class TypingController : ActController
|
||||
{
|
||||
public List<String> submissions;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public GameObject actNamePrefab;
|
||||
public GameObject actDescriptionPrefab;
|
||||
public GameObject timerPrefab;
|
||||
public GameObject submissionFieldPrefab;
|
||||
public GameObject submitPrefab;
|
||||
public GameObject submittedCountPrefab;
|
||||
|
||||
[Header("Objects")]
|
||||
protected Text actName;
|
||||
protected Text actDescription;
|
||||
protected Timer actTimer;
|
||||
protected InputField submissionField;
|
||||
protected Submit submit;
|
||||
protected Text submittedCount;
|
||||
|
||||
protected override void Start() {
|
||||
base.Start();
|
||||
submissions = new List<string>();
|
||||
}
|
||||
|
||||
public override void ActInit() {
|
||||
base.ActInit();
|
||||
|
||||
//Load settings
|
||||
TypingSettings typingSettings = settings as TypingSettings;
|
||||
|
||||
//Init actName Text
|
||||
actName = Instantiate(actNamePrefab, canvas.transform).GetComponent<Text>();
|
||||
actName.text = typingSettings.actName;
|
||||
|
||||
//Init actDescription Text
|
||||
actDescription = Instantiate(actDescriptionPrefab, canvas.transform).GetComponent<Text>();
|
||||
actDescription.text = typingSettings.actDescription;
|
||||
|
||||
//Init actTimer
|
||||
actTimer = Instantiate(timerPrefab, canvas.transform).GetComponent<Timer>();
|
||||
actTimer.TimerSet(typingSettings.timeLimit);
|
||||
|
||||
//Init submissionInputField
|
||||
submissionField = Instantiate(submissionFieldPrefab, canvas.transform).GetComponent<InputField>();
|
||||
|
||||
//Init submit Button
|
||||
submit = Instantiate(submitPrefab, canvas.transform).GetComponent<Submit>();
|
||||
submit.typingController = this;
|
||||
submit.inputField = submissionField;
|
||||
|
||||
//Init submissionCount Text
|
||||
submittedCount = Instantiate(submittedCountPrefab, canvas.transform).GetComponent<Text>();
|
||||
submittedCount.text = "";
|
||||
}
|
||||
|
||||
public override void ActStart() {
|
||||
base.ActStart();
|
||||
|
||||
//Enable submissionField and submit Button
|
||||
submissionField.interactable = true;
|
||||
submit.GetComponent<Button>().interactable = true;
|
||||
|
||||
//Focus on submissionField
|
||||
eventSystem.SetSelectedGameObject(submissionField.gameObject);
|
||||
|
||||
//Start timer
|
||||
actTimer.OnTimeOut += new Action(ActEnd);
|
||||
actTimer.TimerStart();
|
||||
}
|
||||
|
||||
public override void ActEnd() {
|
||||
base.ActEnd();
|
||||
|
||||
//Disable submissionField and submit Button
|
||||
submissionField.interactable = false;
|
||||
submit.GetComponent<Button>().interactable = false;
|
||||
|
||||
//Create results
|
||||
results = new TypingResults(submissions.ToArray());
|
||||
}
|
||||
|
||||
public override void ActCleanup() {
|
||||
base.ActCleanup();
|
||||
|
||||
Destroy(actName.gameObject);
|
||||
Destroy(actDescription.gameObject);
|
||||
Destroy(actTimer.gameObject);
|
||||
Destroy(submissionField.gameObject);
|
||||
Destroy(submit.gameObject);
|
||||
Destroy(submittedCount.gameObject);
|
||||
}
|
||||
|
||||
public void Submit(string submission) {
|
||||
if(submission != "") {
|
||||
submissions.Add(submission);
|
||||
submittedCount.text = String.Format("Submitted: {0}", submissions.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
using System;
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class TypingSettings : ActSettings {
|
||||
public float timeLimit = 99f;
|
||||
public string actName = "Untitled";
|
||||
public string actDescription = "This Act is missing a description.";
|
||||
public string destinationPool = "default";
|
||||
|
||||
public TypingSettings(float timeLimit, string actName, string actDescription, string destinationPool) {
|
||||
this.type = "Typing";
|
||||
this.timeLimit = timeLimit;
|
||||
this.actName = actName;
|
||||
this.actDescription = actDescription;
|
||||
this.destinationPool = destinationPool;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
using System;
|
||||
|
||||
|
||||
public class Viewer {
|
||||
public int id;
|
||||
}
|
8
Assets/Code/Viewer.meta
Normal file
8
Assets/Code/Viewer.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a497e85620cc42944b8561c2059342ac
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
19
Assets/Code/Viewer/ActViewer.cs
Normal file
19
Assets/Code/Viewer/ActViewer.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
namespace BetterTee.Viewer
|
||||
{
|
||||
|
||||
public class ActController
|
||||
{
|
||||
[Header("Settings")]
|
||||
public ActSettings settings = null;
|
||||
protected ActPhase phase = ActPhase.NONE;
|
||||
|
||||
[Header("Objects")]
|
||||
public Canvas canvas = null;
|
||||
public EventSystem eventSystem = null;
|
||||
}
|
||||
|
||||
}
|
11
Assets/Code/Viewer/ActViewer.cs.meta
Normal file
11
Assets/Code/Viewer/ActViewer.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 46e22a25283addd4c8d9d9de963462ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/Code/Viewer/ViewerMainController.cs
Normal file
13
Assets/Code/Viewer/ViewerMainController.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using Mirror;
|
||||
|
||||
|
||||
namespace BetterTee.Viewer
|
||||
{
|
||||
|
||||
public class ViewerMainController : MonoBehaviour
|
||||
{
|
||||
}
|
||||
|
||||
}
|
11
Assets/Code/Viewer/ViewerMainController.cs.meta
Normal file
11
Assets/Code/Viewer/ViewerMainController.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7de9e5b69cd5a9c4796053227593c096
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
206
Assets/Scenes/Viewer.unity
Normal file
206
Assets/Scenes/Viewer.unity
Normal file
|
@ -0,0 +1,206 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 11
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_UseShadowmask: 1
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &1600768605
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1600768608}
|
||||
- component: {fileID: 1600768607}
|
||||
- component: {fileID: 1600768606}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &1600768606
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1600768605}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &1600768607
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1600768605}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 1
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &1600768608
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1600768605}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
@ -1,6 +1,6 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 546b7440efcb5644c8243bc3b3d2e743
|
||||
TextScriptImporter:
|
||||
guid: 73fa8e1d2e6de384a94ce9ff74269804
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
Loading…
Reference in a new issue