Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: seanhess/uarbg2
base: e0bce2e957
...
head fork: seanhess/uarbg2
compare: master
  • 8 commits
  • 13 files changed
  • 0 commit comments
  • 1 contributor
View
9 Makefile
@@ -1,6 +1,11 @@
-all: build-ts
+all: build
-build-ts:
+build:
tsc --out public/main.js public/app.ts
+install:
+ npm install && bower install
+
+
+
View
59 README.md
@@ -3,42 +3,51 @@ uarbg2
Underwater Adventure Rocket Bazooka Guys v2
-
Install
-------
-* npm install
-* bower install
-* node_modules/.bin/coffee app.coffee
-
+ make install
Compiling
---------
-This should compile EVERYTHING, since app includes the controllers, and the controllers import the services
-
- tsc --module amd public/app.ts
-
-You still need to add everything to public/main.js to get it to load
+ make
-Todo
-----
-* matchmaking via geolocation
-
-* Skinning the main screen
+Needs
+-----
+* better explosion / death graphic
+* explosion and rocket in same format
-* Boot old players! Save your player version
+Hit List
+--------
+* Explosion (NEED: explosion and rocket in the same format)
+* Rocket animation
+* (bug) you can kill yourself?
+* (bug) disconnect from missiles too (in game)
+* (clean) use signals/events instead of $rootScope.broadcast
+* (clean) going back to the main page should clean up the game.
+* (idea) switch game/matches when you switch matches?
+* DONE (bug) loop music
+* DONE (bug) current player not set when you check winner? BIG ONE: the old Players object is kicking around, and IT gets all set up and good to go, but the new one doesn't
+* DONE (bug) must click to play
+* DONE (bug) multiple taunt bubbles. umm... no
+* DONE (bug) move/fire after dead
+* DONE (bug) rounds / winning
+* DONE (bug) closed-lid players
-HitList
-------
-* Winning Bug/ Dead player moves. Too many points
-* Explosion
-* Unlocking Payments
+Next Features?
+-------------
+* 3... 2... 1... Fight!
+* facebook / twitter login
+* invite only
-Skinning
-* New backgrounds!
-* Bring the playerCard to the main screen
-* Logo with padding and looking nicer
+Not Yet
+-------
+* Coral / Walls
+* Powerups
+* Update payments
+* matchmaking via geolocation
+* Cannonical server? Ditch firebase?
View
2  package.json
@@ -21,4 +21,4 @@
"stylus": "0.30.1",
"nib": "0.8.2"
}
-v
+}
View
74 public/controllers/GameCtrl.ts
@@ -20,7 +20,7 @@ angular.module('controllers')
// DEBUG: you can set ?debugPlayerName and just hit refresh over and over to reconnect
if ($routeParams.debugPlayerName)
- CurrentPlayer.player = {name: $routeParams.debugPlayerName, avatar:"player" + Math.floor(Math.random()*6), state: "alive", x:0, y:0, wins:0, losses:0, version:AppVersion}
+ CurrentPlayer.player = {name: $routeParams.debugPlayerName, avatar:"player" + Math.floor(Math.random()*6), state: "alive", x:0, y:0, wins:0, losses:0, version:AppVersion, direction:Board.DOWN}
// only play if you are identified
if (!CurrentPlayer.player)
@@ -33,7 +33,7 @@ angular.module('controllers')
//return
//}
- var players = Players.connect($scope.gameId)
+ var players = Players.connect($scope.gameId, "Game")
Players.join(players, CurrentPlayer.player)
$scope.players = players
@@ -53,7 +53,7 @@ angular.module('controllers')
// AUDIO
- //SoundEffects.music()
+ SoundEffects.music()
$scope.test = function() {
//SoundEffects.rocket()
@@ -73,25 +73,12 @@ angular.module('controllers')
return null
}
- function getSprite(newDirection) {
- var slide,
- previousDirection = players.current.direction,
- previous = players.current.sprite;
-
- if(previousDirection === newDirection) {
- slide = ++previous % 3;
- } else {
- slide = 1;
- }
-
- return slide;
- }
-
// ignore ALL key presses if they are dead
$scope.keypress = function (e) {
- // you can do ANYTHING if you are dead
+ // you can do ANYTHING if you are dead, or if the game is currently OVER
if (!Players.isAlive(players.current)) return
+ if (players.winner) return
if (e.keyCode === 32)
return Missiles.fireMissile(missiles, players.current)
@@ -106,46 +93,25 @@ angular.module('controllers')
players.current.x = position.x
players.current.y = position.y
players.current.direction = position.direction
- console.log(players.current.direction)
-
Players.move(players, players.current);
- // you need:
- // a list of updates: { x: 1, y: 2, direction: 'down' }
-
- //players.current.walking = true;
-
- //setTimeout(function(){
- //$scope.$apply(function() {
- //players.current.walking = false;
- //Players.move(players, players.current);
- //});
- //}, 500);
+ // WILL I HIT ANY OTHER PLAYERS?
- /*players.current[location.axis] = location.location;
- players.current.direction = location.direction;
- players.move(players.current);*/
-
- // WILL I HIT ANY OTHER PLAYERS?
-
- //var collision = false;
- //Players.alivePlayers(players.all).forEach(function(p:IPlayer){
- //if (p.name != players.current.name && p.state != "dead") {
- //if (location.axis == "x") {
- //if (p.x == location.location && p.y == players.current.y) collision = true;
- //}
- //if (location.axis == "y") {
- //if (p.y == location.location && p.x == players.current.x) collision = true;
- //}
- //}
- //});
- //if (!collision) {
-
-
- //} else {
- //// we can play a collision sound here!
+ //var collision = false;
+ //Players.alivePlayers(players.all).forEach(function(p:IPlayer){
+ //if (p.name != players.current.name && p.state != "dead") {
+ //if (location.axis == "x") {
+ //if (p.x == location.location && p.y == players.current.y) collision = true;
+ //}
+ //if (location.axis == "y") {
+ //if (p.y == location.location && p.x == players.current.x) collision = true;
//}
//}
- // }
+ //});
+ //if (!collision) {
}
+
+ $scope.$on('$destroy', function() {
+ Players.disconnect(players)
+ });
})
View
6 public/controllers/Identify.ts
@@ -43,7 +43,7 @@ angular.module('controllers').controller('IdentifyCtrl', function($scope: Identi
$scope.gameId = $scope.player.gameId || "global"
// [ ] detect which game to join ("global")
- var players = Players.connect($scope.gameId)
+ var players = Players.connect($scope.gameId, "Identify")
$scope.players = players
// available avatars
@@ -96,6 +96,10 @@ angular.module('controllers').controller('IdentifyCtrl', function($scope: Identi
return ($scope.player && $scope.player.avatar == name)
}
+ $scope.$on('$destroy', function() {
+ Players.disconnect(players)
+ });
+
})
View
5 public/directives/keys.ts
@@ -1,14 +1,15 @@
///<reference path="../def/angular.d.ts"/>
///<reference path="../def/jquery.d.ts"/>
-console.log("KEYPRESS")
angular.module('directives')
.directive('keypress', function($parse) {
return function(scope:ng.IScope, element:JQuery, attrs) {
// element is a jquery element
- // focus the div
+ // focus the div. without the first line it doesn't get keyboard events.
+ // without the second you have to click on it
element.attr('tabindex', 0)
+ element.focus()
var onPress = $parse(attrs.keypress)
var isPressed = false
View
27 public/directives/sprite.ts
@@ -1,21 +1,5 @@
///<reference path="../def/angular.d.ts"/>
-/*
-
-// sprite-walking="player.walking"
-// sprite: generic, plays through different sprites on a sheet
-// hmm... I'd like to reuse some stuff
-
-
-SPRITES: in general, make them change vertically, so you just change the background-y
-
-... this should be defined in the CSS, no?
-
-PERSON: bind to direction
-PERSON: play through multiple states
-*/
-
-
angular.module('directives')
// simple directive that updates the background-y given a direction
@@ -45,6 +29,13 @@ angular.module('directives')
}
})
+// animates through N background states, all at 50px (of course) :)
+.directive('spriteAnimate', function() {
+ return function(scope:ng.IScope, element:JQuery, attrs) {
+
+ }
+})
+
// Now, sprite-walking. I need to know when either x or y changes
.directive('spriteWalking', function(Board:IBoard) {
return function(scope:ng.IScope, element:JQuery, attrs) {
@@ -64,6 +55,7 @@ angular.module('directives')
frame = 0
stopWalking() // don't double animate!
interval = setInterval(animateFrame, FRAME_DURATION)
+ animateFrame()
}
function stopWalking() {
@@ -79,8 +71,7 @@ angular.module('directives')
if (frame >= TOTAL_FRAMES) stopWalking()
}
- scope.$watch(attrs.spriteWalking + ".x", startWalking)
- scope.$watch(attrs.spriteWalking + ".y", startWalking)
+ attrs.$observe('spriteWalking', startWalking)
}
})
View
10 public/partials/game.html
@@ -28,18 +28,16 @@
<div id="board" keypress="keypress(e)" ng-click="test()">
- <h1 class="winner" ng-show="players.winner">{{players.winner.name}} Wins!</h1>
+ <h1 class="winner" ng-show="players.winner">{{players.winner}} Wins!</h1>
<div class="player avatar {{player.avatar}}"
ng-repeat="player in players.all | filter:{state:'alive'}"
ng-style="player | position"
sprite-direction="player.direction"
- sprite-walking="player"
+ sprite-walking="{{player.x}} {{player.y}}"
>
- <!--sprite-walking="player.x + player.y"-->
-
- <div class="taunt triangle-border left" ng-show="players.taunt">{{players.taunt}}</div>
+ <div class="taunt triangle-border left" ng-show="player.taunt">{{player.taunt}}</div>
</div>
<div ng-repeat="missile in missiles.all">
<div class="missile {{missile.direction}}" ng-style="missile | position"></div>
@@ -51,6 +49,6 @@ <h1 class="winner" ng-show="players.winner">{{players.winner.name}} Wins!</h1>
<div class="version">v{{version}}</div>
- <div class="instructions" style="position: absolute; bottom: 20px; color: white">Use arrow keys to move. Space to fire. If you can't move, try clicking the blue board. If someone wins, the game restarts in 3 seconds. If it totally screws up or you are invisible for more than 5 seconds, refresh the page and re-join. </div>
+ <div class="instructions" style="position: absolute; bottom: 20px; color: white">Use arrow keys to move. Space to fire. If someone wins, the game restarts in 2 seconds.</div>
</div>
View
2  public/services/AppVersion.ts
@@ -3,5 +3,5 @@
angular.module('services')
.factory('AppVersion', function():string {
- return "1.1"
+ return "1.2"
})
View
1  public/services/FB.ts
@@ -16,6 +16,7 @@ module fire {
child(name:string);
val();
on(event:string, cb:IRefCB);
+ off(event:string, cb:IRefCB);
set(val:any);
removeOnDisconnect();
}
View
12 public/services/Missiles.ts
@@ -32,6 +32,8 @@ angular.module('services')
}
function connect(gameId:string, players:IPlayerState):IMissileState {
+
+ console.log("M.connect", players.id)
var missilesRef = FB.game(gameId).child('missiles')
var all = []
@@ -102,9 +104,11 @@ angular.module('services')
// Check to see if the missile hits anyone
var hitPlayer = <IPlayer> Board.findHit(players.all, missile)
if (hitPlayer) {
- explodeMissile(missile)
- if (hitPlayer == players.current)
- Players.killPlayer(players, players.current, missile.sourcePlayer)
+ explodeMissile(missile) // if you see it hit, then remove it
+
+ // if it's YOUR missile, blow them up!
+ if (missile.sourcePlayer == players.current.name)
+ Players.killPlayer(players, hitPlayer, missile.sourcePlayer)
}
}
@@ -118,6 +122,6 @@ angular.module('services')
}
function onRemovedMissile(missile) {
- console.log("onRemovedMissile()")
+
}
})
View
172 public/services/Players.ts
@@ -10,6 +10,7 @@
interface IPlayer {
x:number;
y:number;
+ direction:string;
wins:number;
losses:number;
@@ -17,30 +18,30 @@ interface IPlayer {
name:string;
avatar:string;
- direction?:string;
- message?:string;
+ taunt?:string;
killer?:string;
// alive or dead
state:string;
-
- // move this off of player
- walking?:bool;
- sprite?:number;
}
// only variables
interface IPlayerState {
current: IPlayer;
- winner: IPlayer;
- taunt: string;
+ winner: string;
isPaid: bool;
all: IPlayer [];
+ id?: string;
// private stuff. not for binding
myname:string;
gameRef:fire.IRef;
playersRef:fire.IRef;
+
+ boundOnJoin?:fire.IRefCB;
+ boundOnUpdate?:fire.IRefCB;
+ boundOnQuit?:fire.IRefCB;
+ boundOnWinner?:fire.IRefCB;
}
// only methods
@@ -51,15 +52,19 @@ interface IPlayerService {
playerByName(players:IPlayer[], name:string):IPlayer;
latestVersion(players:IPlayer[]):string;
- connect(gameId:string):IPlayerState;
+ connect(gameId:string, id:string):IPlayerState;
+ disconnect(state:IPlayerState);
join(state:IPlayerState, player:IPlayer);
killPlayer(state:IPlayerState, player:IPlayer, killerName:string);
move(state:IPlayerState, player:IPlayer);
+
+ // TODO no reset, make a NEW game
+ resetGame(state:IPlayerState);
}
angular.module('services')
-.factory('Players', function($rootScope:ng.IScope, FB:IFirebaseService, Board:IBoard, AppVersion:any):IPlayerService {
+.factory('Players', function($rootScope:ng.IScope, FB:IFirebaseService, Board:IBoard, AppVersion:string):IPlayerService {
// the big cheese. Does the deed
// you can make fancy bindings here, no?
@@ -72,10 +77,12 @@ angular.module('services')
connect: connect,
join: join,
killPlayer: killPlayer,
- move: move
+ move: move,
+ resetGame: resetGame,
+ disconnect: disconnect,
}
- function connect(gameId:string):IPlayerState {
+ function connect(gameId:string, id:string):IPlayerState {
var gameRef = FB.game(gameId)
var playersRef = gameRef.child('players')
@@ -87,19 +94,34 @@ angular.module('services')
current: null,
winner: null,
- taunt: null,
isPaid: isPaid(),
- all: []
+ all: [],
+ id: id,
}
+ state.boundOnJoin = FB.apply((p) => onJoin(state,p))
+ state.boundOnUpdate = FB.apply((p) => onUpdate(state,p))
+ state.boundOnQuit = FB.apply((p) => onQuit(state,p))
+ state.boundOnWinner = FB.apply((n) => onWinner(state,n))
+
// better way to bind? nope! that's what they are for!
- playersRef.on('child_added', FB.apply((p) => onJoin(state,p)))
- playersRef.on('child_changed', FB.apply((p) => onUpdate(state,p)))
- playersRef.on('child_removed', FB.apply((p) => onQuit(state,p)))
+ playersRef.on('child_added', state.boundOnJoin)
+ playersRef.on('child_changed', state.boundOnUpdate)
+ playersRef.on('child_removed', state.boundOnQuit)
+
+ gameRef.child('winner').on('value', state.boundOnWinner)
return state
}
+ function disconnect(state:IPlayerState) {
+ state.playersRef.off('child_added', state.boundOnJoin)
+ state.playersRef.off('child_changed', state.boundOnUpdate)
+ state.playersRef.off('child_removed', state.boundOnQuit)
+
+ state.gameRef.child('winner').off('value', state.boundOnWinner)
+ }
+
function isAlive(p:IPlayer):bool {
return (p.state == STATE.ALIVE)
}
@@ -115,13 +137,12 @@ angular.module('services')
player.x = Board.randomX()
player.y = Board.randomY()
- player.sprite = 1
player.direction = Board.DOWN
player.state = STATE.ALIVE
player.wins = player.wins || 0
player.losses = player.losses || 0
- player.message = null
- player.version = AppVersion.num
+ player.taunt = null
+ player.version = AppVersion
var ref = state.playersRef.child(player.name)
ref.removeOnDisconnect();
@@ -130,6 +151,7 @@ angular.module('services')
// what can change on a person?
function onJoin(state:IPlayerState, player:IPlayer) {
+ // state.current needs to refer to the SAME player you add to the array
if (!state.current && player.name == state.myname) {
state.current = player
}
@@ -151,11 +173,13 @@ angular.module('services')
player.state = remotePlayer.state;
player.wins = remotePlayer.wins;
player.losses = remotePlayer.losses;
+ player.taunt = remotePlayer.taunt;
//player.walking = remotePlayer.walking;
if (remotePlayer.killer) player.killer = remotePlayer.killer
if (player.state == STATE.DEAD) {
$rootScope.$broadcast("kill", player)
+ // EVERYONE needs to check the win, because otherwise the game doesn't end!
checkWin(state)
}
}
@@ -164,84 +188,78 @@ angular.module('services')
state.all = state.all.filter((p) => p.name != player.name)
}
- function checkWin(state:IPlayerState) {
- var alive = alivePlayers(state.all)
+ function onWinner(state:IPlayerState, name:string) {
- if (alive.length > 1) return
- var winner = alive[0]
- if (state.current == null || winner != state.current) return
-
- // only if is ME
- // why not share the winner with everyone?
- winner.wins += 1
- state.playersRef.child(winner.name).child("wins").set(winner.wins)
- state.gameRef.child("winner").removeOnDisconnect();
- FB.update(state.gameRef.child("winner"), winner)
- // Nobody else should be able to act (already because they are dead)
+ // ignore nulls
+ if (!name) {
+ state.winner = name
+ return
+ }
- // game is set to OVER (missiles finish hitting? like, can you still die?)
- // save the WINNER!
+ // ignore if it hasn't changed
+ if (name == state.winner) return
- // YOU WIN
+ state.winner = name
+ console.log("WE HAVE A WINNER", state.winner)
+ $rootScope.$broadcast("winner", name)
- // kick the game back to zero
- // restart the game in 3 seconds!
- // then turn everyone back to alive! (the winner does this?)
+ // Now EVERYONE resets the game together. Since we're all setting it to the same state, it's ok.
+ setTimeout(() => resetGame(state), 1000)
+ setTimeout(() => startGame(state), 2000)
}
- function onWinner(state:IPlayerState, player:IPlayer) {
-
- // this can get called with null
- if (!player) {
- state.winner = null
- state.taunt = null
- return
- }
-
- // don't "WIN" twice if you're already the winner
- if (state.winner && state.winner.name == player.name)
- return
-
- // set the winner on all computers
- state.winner = player
- state.taunt = TAUNT_LIST[Math.floor(Math.random()*TAUNT_LIST.length)];
+ // resets game, but does NOT make it playable
+ // only resets YOU. any players not paying attention don't get reset. they get REMOVED?
+ // at least we can make them be dead
+ function resetGame(state:IPlayerState) {
+ console.log("Initialize Game")
- // only one person should reset the game
- //console.log("ON WINNER")
- //if (players.current) console.log(" - me ", players.current.name)
- //if (player) console.log(" - win", player.name)
- //if (players.winner) console.log(" - old", players.winner.name)
- //console.log("PASSED")
+ state.current.x = Board.randomX()
+ state.current.y = Board.randomY()
+ state.current.direction = Board.DOWN
+ state.current.state = STATE.ALIVE
+ state.current.taunt = null
- if (state.current && state.current.name == player.name) {
- setTimeout(() => resetGame(state), 3000)
- }
+ FB.update(state.playersRef.child(state.current.name), state.current)
}
- function resetGame(state:IPlayerState) {
- console.log("Initialize Game")
- // build walls?? (how t
- // for each player, make them alive
+ // makes the game playable
+ function startGame(state:IPlayerState) {
+ console.log("START Game!")
state.gameRef.child('winner').remove()
-
- state.all.forEach((player) => {
- player.x = Board.randomX()
- player.y = Board.randomY()
- player.sprite = 1
- player.direction = Board.DOWN
- player.state = STATE.ALIVE
- FB.update(state.playersRef.child(player.name), player)
- })
}
// killPlayer ONLY happens from the current player's perspective. yOu can only kill yourself
function killPlayer(state:IPlayerState, player:IPlayer, killerName:string) {
+ console.log("KILL", player.name, "by", killerName)
player.state = STATE.DEAD
player.losses += 1
player.killer = killerName
FB.update(state.playersRef.child(player.name), player)
}
+ // EVERYONE sets winner / game state to over
+ // but only the winner can add his score if he's paying attention
+ function checkWin(state:IPlayerState) {
+ var alive = alivePlayers(state.all)
+ if (alive.length > 1) return
+
+ var winner = alive[0]
+ console.log("WINNER", winner)
+ //if (state.current == null || winner != state.current) return
+
+ // Game is OVER, set the winner
+ state.gameRef.child("winner").removeOnDisconnect();
+ state.gameRef.child("winner").set(winner.name)
+
+ // only if it is ME, then give yourself a point and taunt
+ if (winner.name == state.current.name) {
+ winner.wins += 1
+ winner.taunt = TAUNT_LIST[Math.floor(Math.random()*TAUNT_LIST.length)];
+ FB.update(state.playersRef.child(winner.name), winner)
+ }
+ }
+
function move(state:IPlayerState, player:IPlayer) {
var playerRef = state.playersRef.child(player.name)
FB.update(playerRef, player)
View
1  public/services/SoundEffects.ts
@@ -15,6 +15,7 @@ angular.module('services')
.factory('SoundEffects', function():ISoundEffectsService {
var bgMusic = new Audio("/audio/g-style.mp3")
+ bgMusic.loop = true
//var underwater = new Audio("/audio/Underwater.mp3")
var epic = new Audio("/audio/UnderwaterEpicBattle.mp3")

No commit comments for this range

Something went wrong with that request. Please try again.