-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclipview.js
134 lines (121 loc) · 5.18 KB
/
clipview.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/// <summary> A UI object to store nanomunchers that can be dropped by
/// a player.
/// </summary>
/// <remarks>
/// <para> The clip contains nanomunchers initialized with random programs.
/// For the sake of gameplay experience, the tedium of programming
/// nanomunchers did not seem appealing.
/// </para>
/// <remarks>
var ClipView = function(paper, topLeft, size, numMunchers, playerColor, player_id){
this.size = size;
this.paper = paper;
var topLeft = topLeft;
var clipBottomRight = topLeft.add(size);
var clipBottomLeft = new Point(topLeft.x, clipBottomRight.y);
var topRight = new Point(clipBottomRight.x, topLeft.y);
// Vertical spacing and size of munchers.
var spacing = Math.floor(size.y / numMunchers);
var radius = Math.floor((spacing * 0.75) / 2);
// Compute origin and step down clip placing nanomunchers.
var currentSpot = new Point(topLeft.x + Math.floor(size.x / 2),
topLeft.y + Math.floor(spacing / 2));
this.interval = new Point(0, spacing);
this.currentMuncher = 1;
this.numMunchers = numMunchers;
this.ready = true;
// A player id used to fire the correct fire sound.
this.player_id = player_id
// Make sure we open the door inwards.
var hinges = [clipBottomLeft, clipBottomRight];
this.doorHinge = Array.min(hinges, function(p){
return Math.abs(paper.width/2 - p.x);
});
// Open the door beyond parallel with vertical wall for visual quality.
if(this.doorHinge === clipBottomLeft){
this.rotationDegrees = 100;
}else{
this.rotationDegrees = -100;
}
// Draw sides and top of clip:
this.clipSidesPath = paper.path("M" + clipBottomLeft.toS() + " " +
"L" + topLeft.toS() + " " +
"L" + topRight.toS() + " " +
"L" + clipBottomRight.toS());
// Door is separate so that it may open.
this.doorPath = paper.path("M" + clipBottomLeft.toS() + " " +
"L" + clipBottomRight.toS());
// Put all MuncherViews in the same canvas element set while stepping
// down the clip.
this.muncherViews = [];
this.canvasElements = paper.set()
for(var i = 0; i < numMunchers; i++){
var program = Muncher.randomProgram();
var muncherView = new MuncherView(GameUI.paper, radius*2, currentSpot,
program, playerColor, true);
this.muncherViews.push(muncherView);
this.canvasElements.push(muncherView.canvasElements);
currentSpot = currentSpot.add(this.interval);
}
}
// Timings for animation events.
ClipView.prototype.DOOR_OPEN_MS = 800;
ClipView.prototype.DOOR_CLOSE_MS = 180;
ClipView.prototype.POP_MUNCHER_MS = 500;
/// <summary> Trigger door open animation. </summary>
ClipView.prototype.openDoor = function(callback){
this.doorPath.animate({transform: "R" + this.rotationDegrees + "," +
this.doorHinge.toS()},
this.DOOR_OPEN_MS, "elastic", callback)
}
/// <summary> Trigger door close animation. </summary>
ClipView.prototype.closeDoor = function(callback){
this.doorPath.animate({transform: "R" + 0 + "," +
this.doorHinge.toS()},
this.DOOR_CLOSE_MS, "<", callback)
}
/// <summary> Eject muncher at the botton of the clip. </summary>
ClipView.prototype.popMuncher = function(){
if(this.ready && this.muncherViews.length > 0){
// Return muncher program for the ejected muncher.
var muncherView = this.muncherViews.pop();
this.ready = false;
this.openDoor();
// Callback to perform shift down animation and eject animation.
window.setTimeout(function(){
var muncher = this.canvasElements.pop();
// Shift all munchers down.
var shiftOffset = this.interval.mul(this.currentMuncher);
// Hide text.
muncherView.hideText();
// Eject the last muncher.
var paperSizeY = new Point(0, this.paper.height);
var currentLocY = new Point(0, muncherView.getLoc().y);
var ejectOffset = paperSizeY.add(currentLocY.add(this.interval.mul(
this.numMunchers)));
playSound("fire" + this.player_id);
muncher.animate({transform: "T" +
muncherView.animationOffset.add(ejectOffset).toS()},
this.POP_MUNCHER_MS, "<",
// Callback to see there are still munchers remaining.
function(){
window.setTimeout(function(){
this.closeDoor(function(){
this.ready = this.currentMuncher <=
this.numMunchers;}.bind(this));
}.bind(this), this.DOOR_OPEN_MS*0.15);
}.bind(this));
}.bind(this), this.DOOR_OPEN_MS*0.15);
return muncherView.program;
}
}
/// <summary> Return whether the clip is empty. </summary>
ClipView.prototype.empty = function(){
return this.muncherViews.length === 0;
}
/// <summary> Clean up the canvas elements. </summary>
ClipView.prototype.destroyCanvasElements = function(){
this.canvasElements.remove();
this.doorPath.remove();
this.clipSidesPath.remove();
}