More games!

This commit is contained in:
Chen Asraf
2016-03-29 22:29:38 +03:00
parent 2b8f7441a2
commit 4f2a80e86f
18 changed files with 304 additions and 69 deletions

1
.gitignore vendored
View File

@@ -63,3 +63,4 @@ target/
bower_components/
static/*
!static/.keep
!static/images

60
app.py
View File

@@ -15,45 +15,61 @@ env.load_path = [
os.path.join(os.path.dirname(__file__), 'bower_components'),
]
bower_files = [
bower_js = [
'jquery/dist/jquery.min.js',
# 'angularjs/angular.min.js',
'bootstrap/dist/js/bootstrap.min.js',
'underscore/underscore-min.js',
]
receiver_js_files = glob.glob(os.path.join(
os.path.dirname(__file__), 'coffee', 'receiver', '*.coffee'))
sender_js_files = glob.glob(os.path.join(
os.path.dirname(__file__), 'coffee', 'sender', '*.coffee'))
receiver_css_files = glob.glob(os.path.join(
os.path.dirname(__file__), 'sass', 'receiver', '*.scss'))
sender_css_files = glob.glob(os.path.join(
os.path.dirname(__file__), 'sass', 'sender', '*.scss'))
bower_css = [
'bootstrap/dist/css/bootstrap.min.css',
'bootstrap/dist/css/bootstrap-theme.min.css',
]
receiver_js_files = map(lambda x: x[x.find(os.path.sep)+1:], receiver_js_files)
sender_js_files = map(lambda x: x[x.find(os.path.sep)+1:], sender_js_files)
receiver_css_files = map(lambda x: x[x.find(os.path.sep)+1:], receiver_css_files)
sender_css_files = map(lambda x: x[x.find(os.path.sep)+1:], sender_css_files)
receiver_js_files = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(os.path.join('coffee', 'receiver'))
for f in files if f.endswith('.coffee')]
sender_js_files = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(os.path.join('coffee', 'sender'))
for f in files if f.endswith('.coffee')]
receiver_css_files = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(os.path.join('sass', 'receiver'))
for f in files if f.endswith('.scss')]
sender_css_files = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(os.path.join('sass', 'sender'))
for f in files if f.endswith('.scss')]
receiver_js_bundle = bower_files + \
receiver_js_files = map(
lambda x: x[x.find(os.path.sep) + 1:], receiver_js_files)
sender_js_files = map(lambda x: x[x.find(os.path.sep) + 1:], sender_js_files)
receiver_css_files = map(
lambda x: x[x.find(os.path.sep) + 1:], receiver_css_files)
sender_css_files = map(lambda x: x[x.find(os.path.sep) + 1:], sender_css_files)
receiver_js_bundle = bower_js + \
[assets.Bundle(*receiver_js_files, filters='coffeescript',
output='receiver.js')]
sender_js_bundle = bower_files + \
sender_js_bundle = bower_js + \
[assets.Bundle(*sender_js_files, filters='coffeescript',
output='sender.js')]
receiver_css_bundle = bower_css + \
[assets.Bundle(*receiver_css_files, filters='scss',
output='receiver.css')]
sender_css_bundle = bower_css + \
[assets.Bundle(*sender_css_files, filters='scss',
output='sender.css')]
bundles = {
'receiver_js': assets.Bundle(*receiver_js_bundle),
'sender_js': assets.Bundle(*sender_js_bundle),
'receiver_css': assets.Bundle(*receiver_css_files,
filters='scss',
output='receiver.css'),
'sender_css': assets.Bundle(*sender_css_files,
filters='scss',
output='sender.css'),
'receiver_css': assets.Bundle(*receiver_css_bundle),
'sender_css': assets.Bundle(*sender_css_bundle),
}
env.register(bundles)
print receiver_js_files
@app.route("/")
def index():

View File

@@ -9,6 +9,7 @@ window.addEventListener 'load', ->
cast.receiver.logger.setLevelValue 0
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance()
console.log 'Starting Receiver Manager'
window.stateHandler = new StateHandler(new RootState())
# handler for the 'ready' event
castReceiverManager.onReady = (event) ->
@@ -43,16 +44,12 @@ window.addEventListener 'load', ->
# display the message from the sender
displayText JSON.stringify(data)
if 'spinWheel' of data
spinWheel(data.spinWheel)
stateHandler.sendMessage(data)
# inform all senders on the CastMessageBus of the incoming message event
# sender message listener will be invoked
window.messageBus.send event.senderId, event.data
window.spinWheel = (velocity) ->
console.debug 'spinWheel', {wheelSpinning, wheelStopped}
wheel.spin(velocity)
# initialize the CastReceiverManager with an application status message
window.castReceiverManager.start statusText: 'Application is starting'
console.log 'Receiver Manager started'

View File

@@ -0,0 +1,169 @@
class StateHandler
constructor: (@current) ->
@initialState = @current
sendMessage: (message) ->
@current.onMessage(message)
resetState: ->
@current = @initialState
setState: (@current) ->
class StateDefinition
constructor: ({@handler = window.stateHandler} = {}) ->
onMessage: (message) ->
@handler.resetState()
class RootState extends StateDefinition
onMessage: (message) ->
if 'spinWheel' of message and not wheelSpinning
wheel.spin(message.spinWheel)
@setMarker(message.spinWheel)
setMarker: (velocity) ->
y = Math.abs(velocity) / 15 * 100
$('#marker').css bottom: (y / 2) + 'vh'
style = if 15 > y
'blue'
else if 15 < y < 50
'green'
else if 50 < y < 80
'yellow'
else
'red'
$('#marker-line').removeClass 'blue green yellow red'
$('#marker-line').addClass style
setTimeout ->
$('#marker-line').removeClass 'blue green yellow red'
$('#marker-line').addClass 'blue'
$('#marker').css bottom: '0vh'
, 4000
class DialogState extends StateDefinition
id: null
constructor: ({@content, @size = 'md', @classes, @data} = {}) ->
throw Error "Must provide id in prototype" unless @id?
displayText JSON.stringify {@content, @size, @classes}
super
modal = document.createElement('div')
modal.className = 'modal fade in'
modal.id = @id
modal.setAttribute 'role', 'dialog'
modalDialog = document.createElement('div')
modalDialog.className = "modal-dialog modal-#{@size} #{@classes}"
modalContent = document.createElement('div')
modalContent.className = 'modal-content'
modal.setAttribute 'role', 'document'
modalContent.innerHTML = "<h1>#{@_getContent()}</h1>"
modalDialog.appendChild(modalContent)
modal.appendChild(modalDialog)
document.body.appendChild(modal)
@modal = $("##{@id}")
@modal.modal('show')
_getContent: ->
@content
_refreshContent: ->
@modal.find('.modal-content').html @_getContent()
onMessage: ->
@_closeModal()
super
_closeModal: ->
@modal.modal('hide')
setTimeout =>
@modal.remove()
, 1000
class DrinkState extends DialogState
id: 'drink-modal'
class YouTubeState extends DialogState
id: 'youtube-modal'
constructor: ->
super
@playing = no
_getContent: ->
"""
<iframe id="ytplayer-#{@id}" type="text/html" width="640" height="390"
src="http://www.youtube.com/embed/#{@content}"
frameborder="0"/>
"""
onMessage: ->
if not @playing
$("#ytplayer-#{@id}")[0].src += "?autoplay=1"
@playing = yes
else
$("#ytplayer-#{@id}")[0].src = ''
super
class TimeoutState extends DialogState
id: 'timeout'
step: 0
constructor: (options) ->
super
_getContent: ->
switch @step
when 0
"""
<h1>#{@_competitorsImages()}</h1>
<h2>You have #{@data.seconds} to drink as much beer as you can!</h2>
"""
when 1
"""
<h2>#{@_competitorsImages()}</h2>
<h1>#{@_toTimeStr(@data.seconds)}</h1>
"""
else
"<h1>Time's up!</h1>"
_competitorsImages: ->
@data.competitors = @data.competitorsFunc?() unless @data.competitors?
@data.competitors
.map (c) -> "<img src=\"/static/images/#{c.toLowerCase()}.png\" />"
.join(' vs ')
_startTimeout: ->
@interval = window.setInterval =>
@data.seconds -= 1
@_refreshContent()
if @data.seconds < 0
clearInterval @interval
@step++
@_refreshContent()
, 1000
onMessage: ->
return if @step is 1
switch @step
when 0
@_startTimeout()
@step++
when 2
super
return
_contentTemplate: (competitors, time) ->
_toTimeStr: (secs) ->
hours = Math.floor secs / 3600
minutes = Math.floor (secs - (hours * 3600)) / 60
seconds = secs - (hours * 3600) - (minutes * 60)
# hours = "0#{hours}" if hours < 10
minutes = "0#{minutes}" if minutes < 10
seconds = "0#{seconds}" if seconds < 10
"#{minutes}:#{seconds}"

View File

@@ -30,44 +30,57 @@ particles = []
statusLabel = document.getElementById('status_label')
segConfig = [
{
text: 'Drink with a buddy 1'
onWin: ->
displayText "You need to drink with someone else 1"
text: 'Drink with Zeevi'
winState: YouTubeState
stateOptions:
content: 'dQw4w9WgXcQ'
size: 'lg'
}
{
text: 'Drink with a buddy 2'
onWin: ->
displayText "You need to drink with someone else 2"
text: 'Beer Match!'
winState: TimeoutState
stateOptions:
data:
competitorsFunc: ->
amount = Math.round(Math.random())
names = 'Amit Avihad Chen Dor Eran Lior Michael Tom Zeevi'.split(' ')
_.shuffle(names)[0...amount + 2]
}
{
text: 'Drink with a buddy 3'
onWin: ->
displayText "You need to drink with someone else 3"
text: 'Drink with Chen'
winState: DrinkState
stateOptions:
content: 'Drink with Chen'
}
{
text: 'Drink with a buddy 4'
onWin: ->
displayText "You need to drink with someone else 4"
text: 'Drink with Dor'
winState: DrinkState
stateOptions:
content: 'Drink with Dor'
}
{
text: 'Drink with a buddy 5'
onWin: ->
displayText "You need to drink with someone else 5"
text: 'Drink with Amit'
winState: DrinkState
stateOptions:
content: 'Drink with Amit'
}
{
text: 'Drink with a buddy 6'
onWin: ->
displayText "You need to drink with someone else 6"
text: 'Drink with Alon'
winState: DrinkState
stateOptions:
content: 'Drink with Alon'
}
{
text: 'Drink with a buddy 7'
onWin: ->
displayText "You need to drink with someone else 7"
text: 'Drink with Eran'
winState: DrinkState
stateOptions:
content: 'Drink with Eran'
}
{
text: 'Drink with a buddy 8'
onWin: ->
displayText "You need to drink with someone else 8"
text: 'Drink with Lior'
winState: DrinkState
stateOptions:
content: 'Drink with Lior'
}
]
@@ -102,7 +115,7 @@ checkEndDrag = (e) ->
world.removeConstraint mouseConstraint
mouseConstraint = null
if wheelSpinning == false and wheelStopped == true
if Math.abs(wheel.body.angularVelocity) > 7.5
if Math.abs(wheel.body.angularVelocity) > 4.5
wheelSpinning = true
wheelStopped = false
console.log 'good spin'
@@ -165,11 +178,11 @@ update = ->
# console.debug 'update', {wheelSpinning, wheelStopped, angularVelocity: wheel.body.angularVelocity, arrowHasStopped: arrow.hasStopped()}
if wheelSpinning and not wheelStopped and wheel.body.angularVelocity < 0.5 and arrow.hasStopped()
currentSeg = wheel.currentSegment()
console.debug 'checking segment', currentSeg
wheelStopped = true
wheelSpinning = false
# wheel.body.angularVelocity = 0
segConfig[currentSeg]?.onWin?()
seg = segConfig[currentSeg]
if seg.winState
stateHandler.setState new seg.winState seg.stateOptions
draw = ->
# ctx.fillStyle = '#fff';
@@ -275,10 +288,10 @@ class Wheel
ctx.fill()
if @segmentTexts[i].length
ctx.rotate (i + (2/3)) * @deltaPI
ctx.rotate (i + (3/5)) * @deltaPI
ctx.font = '30px sans-serif'
ctx.fillStyle = '#000000'
ctx.fillText(@segmentTexts[i], 70, 0, 180)
ctx.fillText(@segmentTexts[i], 70, 3, 280)
ctx.restore()
i++

View File

@@ -33,4 +33,4 @@ requestSession = ->
chrome.cast.requestSession onRequestSessionSuccess, onLaunchError
sendMessage = (message) ->
session.sendMessage namespace, message, onMessageSuccess
session.sendMessage namespace, JSON.stringify(message), onMessageSuccess

View File

@@ -1,11 +1,10 @@
body {
width : 1280px;
height : 720px;
background : #44a52f;
color : #fff;
padding : 5%;
font-family: "Droid Sans", Calibri, Arial, Tahoma, sans-serif;
overflow: hidden;
width : 100vw;
height : 100vh;
color : #fff;
padding : 5%;
overflow : hidden;
background: linear-gradient(to bottom, #08541b 0%, #44a52f 20%);
}
#drawing_canvas {
position : absolute;
@@ -13,3 +12,40 @@ body {
top : 50%;
transform: translate(-50%, -18%);
}
.modal-content {
color: #333;
}
#marker {
position : absolute;
bottom : 0;
content : "";
border : 20px solid rgba(0,0,0,0);
border-right-color: white;
width : 0;
height : 0;
margin-bottom : -20px;
transition : all 1s ease-in-out;
}
#marker-line {
width : 30px;
height : 50vh;
position : absolute;
top : 50%;
left : 5%;
border : 2px solid white;
box-shadow: 1px 1px 3px 3px rgba(0,0,0,0.3);
transform : translateY(-50%);
transition : all 1.2s ease-in-out;
&.blue {
background: linear-gradient(to bottom, #032a62 0%, #005dea 100%);
}
&.green {
background: linear-gradient(to bottom, #00ce38 0%, #82e573 100%);
}
&.yellow {
background: linear-gradient(to bottom, #ffdb39 0%, #ffa22a 100%);
}
&.red {
background: linear-gradient(to bottom, #831a17 0%, #ff000a 100%);
}
}

BIN
static/images/amit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
static/images/avihad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
static/images/chen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
static/images/dor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
static/images/eran.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
static/images/lior.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
static/images/michael.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
static/images/tom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
static/images/zeevi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -11,8 +11,6 @@
{% endassets %}
<script type="text/javascript"
src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
<script type="text/javascript"
src="//www.gstatic.com/cast/sdk/libs/games/1.0.0/cast_games_receiver.js"></script>
<script type="text/javascript"
src="//cdnjs.cloudflare.com/ajax/libs/p2.js/0.6.0/p2.min.js"></script>
{% assets "receiver_js" %}
@@ -23,12 +21,16 @@
<head>
<body>
<h1>Receiver</h1>
<h1>CastRoulette</h1>
Latest message:
<div id="message"></div>
<canvas id="drawing_canvas"></canvas>
<div id="marker-line" class="blue">
<div id="marker" style="bottom: 0"></div>
</div>
</body>
</html>

View File

@@ -27,6 +27,7 @@
<button type="button"
onclick="sendMessage(document.querySelector('#message').value)">Send message</button>
</div>
<input type="text" id="spin" value="5" /><button type="button" onclick="sendMessage({spinWheel: document.querySelector('#spin').value})">Spin wheel</button>
</body>
</html>