diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc6dd4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +id_rsa +id_rsa.pub +sshtron diff --git a/README.md b/README.md index 39b0fff..b79bb25 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ SSHTron is a multiplayer lightcycle game that runs through SSH. Just run the com $ ssh sshtron.zachlatta.com -_Controls: WASD or vim keybindings to move (**do not use your arrow keys**). Escape or Ctrl+C to exit._ +_Controls: WASD, arrow keys or vim keybindings to move. Escape or Ctrl+C to exit._ ![Demo](static/img/gameplay.gif) diff --git a/game.go b/game.go index 7577475..3b53e15 100644 --- a/game.go +++ b/game.go @@ -45,7 +45,7 @@ func (h *Hub) Run(g *Game) { h.Sessions[s] = struct{}{} case s := <-h.Unregister: if _, ok := h.Sessions[s]; ok { - fmt.Fprint(s, "\r\n\r\n~ End of Line ~ \r\n\r\nRemember to use WASD to move!\r\n\r\n") + fmt.Fprint(s, "\r\n\r\n ~ Bye! ~ \r\n\r\n") // Unhide the cursor fmt.Fprint(s, "\033[?25h") @@ -77,18 +77,26 @@ func (p Position) RoundY() int { type PlayerDirection int const ( - verticalPlayerSpeed = 0.007 - horizontalPlayerSpeed = 0.01 + speedMultiplier = 1 + verticalPlayerSpeed = 0.007 * speedMultiplier + horizontalPlayerSpeed = 0.01 * speedMultiplier playerCountScoreMultiplier = 1.25 playerTimeout = 15 * time.Second - playerUpRune = '⇡' - playerLeftRune = '⇠' - playerDownRune = '⇣' - playerRightRune = '⇢' + //playerUpRune = '⇡' + //playerLeftRune = '⇠' + //playerDownRune = '⇣' + //playerRightRune = '⇢' + playerUpRune = '↑' + playerLeftRune = '←' + playerDownRune = '↓' + playerRightRune = '→' + + //playerTrailHorizontal = '╌' + //playerTrailVertical = '┆' + playerTrailHorizontal = '─' + playerTrailVertical = '│' - playerTrailHorizontal = '┄' - playerTrailVertical = '┆' playerTrailLeftCornerUp = '╭' playerTrailLeftCornerDown = '╰' playerTrailRightCornerDown = '╯' @@ -145,6 +153,7 @@ type Player struct { Name string CreatedAt time.Time Direction PlayerDirection + InitDir PlayerDirection Marker rune Color color.Attribute Pos *Position @@ -172,6 +181,7 @@ func NewPlayer(s *Session, worldWidth, worldHeight int, CreatedAt: time.Now(), Marker: playerDownRune, Direction: PlayerDown, + InitDir: PlayerDown, Color: color, Pos: &Position{startX, startY}, } @@ -192,38 +202,34 @@ func (p *Player) calculateScore(delta float64, playerCount int) float64 { } func (p *Player) HandleUp() { - if p.Direction == PlayerDown { + if p.InitDir == PlayerDown { return } p.Direction = PlayerUp - p.Marker = playerUpRune p.s.didAction() } func (p *Player) HandleLeft() { - if p.Direction == PlayerRight { + if p.InitDir == PlayerRight { return } p.Direction = PlayerLeft - p.Marker = playerLeftRune p.s.didAction() } func (p *Player) HandleDown() { - if p.Direction == PlayerUp { + if p.InitDir == PlayerUp { return } p.Direction = PlayerDown - p.Marker = playerDownRune p.s.didAction() } func (p *Player) HandleRight() { - if p.Direction == PlayerLeft { + if p.InitDir == PlayerLeft { return } p.Direction = PlayerRight - p.Marker = playerRightRune p.s.didAction() } @@ -249,6 +255,21 @@ func (p *Player) Update(g *Game, delta float64) { // If we moved, add a trail segment. if endX != startX || endY != startY { + // Update initial direction + // Needed to prevent players from doing a 180 in one frame + p.InitDir = p.Direction + // Update player direction only after a new frame + switch p.InitDir { + case PlayerUp: + p.Marker = playerUpRune + case PlayerLeft: + p.Marker = playerLeftRune + case PlayerDown: + p.Marker = playerDownRune + case PlayerRight: + p.Marker = playerRightRune + } + var lastSeg *PlayerTrailSegment var lastSegX, lastSegY int if len(p.Trail) > 0 { @@ -320,7 +341,7 @@ type Tile struct { } const ( - gameWidth = 78 + gameWidth = 82 gameHeight = 22 keyW = 'w' @@ -337,6 +358,12 @@ const ( keyK = 'k' keyL = 'l' + // https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#list-of-keyboard-strings + keyUp = 'A' + keyDown = 'B' + keyRight = 'C' + keyLeft = 'D' + keyComma = ',' keyO = 'o' keyE = 'e' @@ -417,15 +444,34 @@ func (gm *GameManager) HandleNewChannel(c ssh.Channel, color string) { fmt.Println(err) break } + if r == keyEscape { + has_more := reader.Buffered() + // not just escape + if has_more > 0 { + r1, _, err := reader.ReadRune() + if err != nil { + fmt.Println(err) + break + } + // Then goes arrow key + if r1 == '[' { + r, _, err = reader.ReadRune() + if err != nil { + fmt.Println(err) + break + } + } + } + } switch r { - case keyW, keyZ, keyK, keyComma: + case keyUp, keyW, keyZ, keyK, keyComma: session.Player.HandleUp() - case keyA, keyQ, keyH: + case keyLeft, keyA, keyQ, keyH: session.Player.HandleLeft() - case keyS, keyJ, keyO: + case keyDown, keyS, keyJ, keyO: session.Player.HandleDown() - case keyD, keyL, keyE: + case keyRight, keyD, keyL, keyE: session.Player.HandleRight() case keyCtrlC, keyEscape: if g.SessionCount() == 1 { diff --git a/sshtron.sh b/sshtron.sh index 416c663..607965b 100755 --- a/sshtron.sh +++ b/sshtron.sh @@ -1,7 +1,12 @@ #!/bin/sh -cd "$SNAP_DATA" +if [ -d "$SNAP_DATA" ]; then + cd "$SNAP_DATA" + [ -f id_rsa ] || "$SNAP"/usr/bin/ssh-keygen -t rsa -N '' -f id_rsa -[ -f id_rsa ] || $SNAP/usr/bin/ssh-keygen -t rsa -N '' -f id_rsa + sshtron > "$SNAP_DATA/sshtron.log" 2>&1 +else + [ -f id_rsa ] || ssh-keygen -t rsa -N '' -f id_rsa -sshtron > "$SNAP_DATA/sshtron.log" 2>&1 + ./sshtron > sshtron.log 2>&1 +fi diff --git a/static/index.html b/static/index.html index e17ffde..89d045d 100644 --- a/static/index.html +++ b/static/index.html @@ -29,7 +29,7 @@

SSH Tron

be playing in seconds.

$ ssh sshtron.zachlatta.com

-

(WASD or vim keybindings for movement, do not use arrow keys)

+

(WASD, arrow keys or vim keybindings for movement)

By @MaxWofford and