littlejsengine 1.18.28 → 1.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FAQ.md +5 -0
- package/README.md +207 -199
- package/dist/littlejs.d.ts +2099 -48
- package/dist/littlejs.esm.js +16251 -10315
- package/dist/littlejs.esm.min.js +13 -1
- package/dist/littlejs.js +15747 -9888
- package/dist/littlejs.min.js +13 -1
- package/dist/littlejs.release.js +15719 -9867
- package/package.json +1 -1
- package/plugins/audioEffects.js +371 -0
- package/plugins/lightSystem.js +5 -3
- package/plugins/math3d.js +870 -0
- package/plugins/medalSystem.js +280 -280
- package/plugins/pluginExport.js +181 -115
- package/plugins/postProcess.js +241 -166
- package/plugins/render3d.js +4006 -0
- package/plugins/textureSheet.js +458 -458
- package/plugins/threejs.js +6 -1
- package/plugins/tweenSystem.js +528 -526
- package/plugins/zzfxm.js +159 -166
- package/src/engine.js +172 -137
- package/src/engineAudio.js +918 -775
- package/src/engineBuild.mjs +3 -0
- package/src/engineDebug.js +15 -8
- package/src/engineDraw.js +1672 -1510
- package/src/engineExport.js +407 -396
- package/src/engineInput.js +1 -1
- package/src/engineLogo.js +4 -3
- package/src/engineMath.js +69 -0
- package/src/engineObject.js +560 -551
- package/src/engineSettings.js +759 -725
- package/src/engineTileLayer.js +3 -3
- package/src/engineUtilities.js +13 -0
- package/src/engineWebGL.js +1005 -941
package/plugins/medalSystem.js
CHANGED
|
@@ -1,280 +1,280 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LittleJS Medal System
|
|
3
|
-
* - Achievement/trophy system for games
|
|
4
|
-
* - Medal class with name, description, icon, and unlock tracking
|
|
5
|
-
* - Automatic saving to local storage
|
|
6
|
-
* - Visual display queue with slide-in notifications
|
|
7
|
-
* - Newgrounds API integration for online achievements
|
|
8
|
-
* - Debug mode to unlock/reset medals during development
|
|
9
|
-
* @namespace Medals
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
'use strict';
|
|
13
|
-
|
|
14
|
-
let debugMedals = false;
|
|
15
|
-
|
|
16
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
17
|
-
// Medals settings
|
|
18
|
-
|
|
19
|
-
/** How long to show medals for in seconds
|
|
20
|
-
* @type {number}
|
|
21
|
-
* @default
|
|
22
|
-
* @memberof Settings */
|
|
23
|
-
let medalDisplayTime = 5;
|
|
24
|
-
|
|
25
|
-
/** How quickly to slide on/off medals in seconds
|
|
26
|
-
* @type {number}
|
|
27
|
-
* @default
|
|
28
|
-
* @memberof Settings */
|
|
29
|
-
let medalDisplaySlideTime = .5;
|
|
30
|
-
|
|
31
|
-
/** Size of medal display
|
|
32
|
-
* @type {Vector2}
|
|
33
|
-
* @default Vector2(640,80)
|
|
34
|
-
* @memberof Settings */
|
|
35
|
-
let medalDisplaySize = vec2(640, 80);
|
|
36
|
-
|
|
37
|
-
/** Set to stop medals from being unlockable (like if cheats are enabled)
|
|
38
|
-
* @type {boolean}
|
|
39
|
-
* @default
|
|
40
|
-
* @memberof Settings */
|
|
41
|
-
let medalsPreventUnlock = false;
|
|
42
|
-
|
|
43
|
-
/** List of all medals
|
|
44
|
-
* @type {Object}
|
|
45
|
-
* @memberof Medals */
|
|
46
|
-
const medals = {};
|
|
47
|
-
|
|
48
|
-
// Engine internal variables not exposed to documentation
|
|
49
|
-
let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
|
|
50
|
-
|
|
51
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
52
|
-
|
|
53
|
-
/** Initialize medals with a save name used for storage
|
|
54
|
-
* - Call this after creating all medals
|
|
55
|
-
* - Checks if medals are unlocked
|
|
56
|
-
* @param {string} saveName
|
|
57
|
-
* @memberof Medals */
|
|
58
|
-
function medalsInit(saveName)
|
|
59
|
-
{
|
|
60
|
-
// check if medals are unlocked
|
|
61
|
-
medalsSaveName = saveName;
|
|
62
|
-
if (!debugMedals)
|
|
63
|
-
{
|
|
64
|
-
let saved = {};
|
|
65
|
-
try { saved = JSON.parse(localStorage[saveName] || '{}'); }
|
|
66
|
-
catch (e) { saved = {}; }
|
|
67
|
-
medalsForEach(medal => {
|
|
68
|
-
medal.unlocked = !!(saved[medal.id] && saved[medal.id].unlocked);
|
|
69
|
-
});
|
|
70
|
-
medalsSave();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// engine automatically renders medals
|
|
74
|
-
engineAddPlugin(undefined, medalsRender);
|
|
75
|
-
|
|
76
|
-
// plugin functions
|
|
77
|
-
function medalsRender()
|
|
78
|
-
{
|
|
79
|
-
if (!medalsDisplayQueue.length) return;
|
|
80
|
-
|
|
81
|
-
// update first medal in queue
|
|
82
|
-
const medal = medalsDisplayQueue[0];
|
|
83
|
-
const time = timeReal - medalsDisplayTimeLast;
|
|
84
|
-
if (!medalsDisplayTimeLast)
|
|
85
|
-
medalsDisplayTimeLast = timeReal;
|
|
86
|
-
else if (time > medalDisplayTime)
|
|
87
|
-
{
|
|
88
|
-
medalsDisplayTimeLast = 0;
|
|
89
|
-
medalsDisplayQueue.shift();
|
|
90
|
-
}
|
|
91
|
-
else
|
|
92
|
-
{
|
|
93
|
-
// slide on/off medals
|
|
94
|
-
const slideOffTime = medalDisplayTime - medalDisplaySlideTime;
|
|
95
|
-
const hidePercent =
|
|
96
|
-
time < medalDisplaySlideTime ? 1 - time / medalDisplaySlideTime :
|
|
97
|
-
time > slideOffTime ? (time - slideOffTime) / medalDisplaySlideTime : 0;
|
|
98
|
-
medal.render(hidePercent);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @callback MedalCallbackFunction - Function that processes a medal
|
|
105
|
-
* @param {Medal} medal
|
|
106
|
-
* @memberof Medals
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
|
-
/** Calls a function for each medal
|
|
110
|
-
* @param {MedalCallbackFunction} callback
|
|
111
|
-
* @memberof Medals */
|
|
112
|
-
function medalsForEach(callback)
|
|
113
|
-
{ Object.values(medals).forEach(medal=>callback(medal)); }
|
|
114
|
-
|
|
115
|
-
/** Reset all medals to locked and persist the cleared catalog
|
|
116
|
-
* @memberof Medals */
|
|
117
|
-
function medalsReset()
|
|
118
|
-
{
|
|
119
|
-
medalsForEach(medal => medal.unlocked = false);
|
|
120
|
-
medalsSave();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function medalsSave()
|
|
124
|
-
{
|
|
125
|
-
if (!medalsSaveName) return;
|
|
126
|
-
const data = {};
|
|
127
|
-
medalsForEach(medal => {
|
|
128
|
-
const entry = {
|
|
129
|
-
name: medal.name,
|
|
130
|
-
description: medal.description,
|
|
131
|
-
icon: medal.icon,
|
|
132
|
-
unlocked: medal.unlocked,
|
|
133
|
-
};
|
|
134
|
-
if (medal.image) entry.src = medal.image.src;
|
|
135
|
-
data[medal.id] = entry;
|
|
136
|
-
});
|
|
137
|
-
localStorage[medalsSaveName] = JSON.stringify(data);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Medal - Tracks an unlockable medal
|
|
144
|
-
* @memberof Medals
|
|
145
|
-
* @example
|
|
146
|
-
* // create a medal
|
|
147
|
-
* const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
|
|
148
|
-
*
|
|
149
|
-
* // initialize medals
|
|
150
|
-
* medalsInit('Example Game');
|
|
151
|
-
*
|
|
152
|
-
* // unlock the medal
|
|
153
|
-
* medal_example.unlock();
|
|
154
|
-
*/
|
|
155
|
-
class Medal
|
|
156
|
-
{
|
|
157
|
-
/** Create a medal object and adds it to the list of medals
|
|
158
|
-
* @param {number} id - The unique identifier of the medal
|
|
159
|
-
* @param {string} name - Name of the medal
|
|
160
|
-
* @param {string} [description] - Description of the medal
|
|
161
|
-
* @param {string} [icon] - Icon for the medal
|
|
162
|
-
* @param {string} [src] - Image location for the medal
|
|
163
|
-
*/
|
|
164
|
-
constructor(id, name, description='', icon='🏆', src)
|
|
165
|
-
{
|
|
166
|
-
ASSERT(id >= 0 && !medals[id]);
|
|
167
|
-
|
|
168
|
-
/** @property {number} - The unique identifier of the medal */
|
|
169
|
-
this.id = id;
|
|
170
|
-
|
|
171
|
-
/** @property {string} - Name of the medal */
|
|
172
|
-
this.name = name;
|
|
173
|
-
|
|
174
|
-
/** @property {string} - Description of the medal */
|
|
175
|
-
this.description = description;
|
|
176
|
-
|
|
177
|
-
/** @property {string} - Icon for the medal */
|
|
178
|
-
this.icon = icon;
|
|
179
|
-
|
|
180
|
-
/** @property {boolean} - Is the medal unlocked? */
|
|
181
|
-
this.unlocked = false;
|
|
182
|
-
|
|
183
|
-
/** @property {HTMLImageElement|undefined} - Source image for the medal icon, if any */
|
|
184
|
-
this.image = undefined;
|
|
185
|
-
if (src)
|
|
186
|
-
(this.image = new Image).src = src;
|
|
187
|
-
|
|
188
|
-
// add this to list of medals
|
|
189
|
-
medals[id] = this;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/** Unlocks a medal if not already unlocked */
|
|
193
|
-
unlock()
|
|
194
|
-
{
|
|
195
|
-
if (medalsPreventUnlock || this.unlocked) return;
|
|
196
|
-
|
|
197
|
-
ASSERT(medalsSaveName, 'save name must be set');
|
|
198
|
-
this.unlocked = true;
|
|
199
|
-
medalsSave();
|
|
200
|
-
medalsDisplayQueue.push(this);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/** Render a medal
|
|
204
|
-
* @param {number} [hidePercent] - How much to slide the medal off screen
|
|
205
|
-
*/
|
|
206
|
-
render(hidePercent=0)
|
|
207
|
-
{
|
|
208
|
-
const context = mainContext;
|
|
209
|
-
const width = min(medalDisplaySize.x,
|
|
210
|
-
const height = medalDisplaySize.y;
|
|
211
|
-
const x =
|
|
212
|
-
const y = -height*hidePercent;
|
|
213
|
-
const backgroundColor = hsl(0,0,.9);
|
|
214
|
-
|
|
215
|
-
// draw containing rect and clip to that region
|
|
216
|
-
context.save();
|
|
217
|
-
context.beginPath();
|
|
218
|
-
context.fillStyle = backgroundColor.toString();
|
|
219
|
-
context.strokeStyle = BLACK.toString();
|
|
220
|
-
context.lineWidth = 3;
|
|
221
|
-
context.rect(x, y, width, height);
|
|
222
|
-
context.fill();
|
|
223
|
-
context.stroke();
|
|
224
|
-
context.clip();
|
|
225
|
-
|
|
226
|
-
// draw the icon
|
|
227
|
-
const gap = vec2(.1, .05).scale(height);
|
|
228
|
-
const medalDisplayIconSize = height - 2*gap.x;
|
|
229
|
-
this.renderIcon(vec2(x + gap.x + medalDisplayIconSize/2, y + height/2), medalDisplayIconSize);
|
|
230
|
-
|
|
231
|
-
// draw the name
|
|
232
|
-
const nameSize = height*.5;
|
|
233
|
-
const descriptionSize = height*.3;
|
|
234
|
-
const pos = vec2(x + medalDisplayIconSize + 2*gap.x, y + gap.y*2 + nameSize/2);
|
|
235
|
-
const textWidth = width - medalDisplayIconSize - 3*gap.x;
|
|
236
|
-
drawTextScreen(this.name, pos, nameSize, BLACK, 0, undefined, 'left', undefined, undefined, textWidth);
|
|
237
|
-
|
|
238
|
-
// draw the description
|
|
239
|
-
pos.y = y + height - gap.y*2 - descriptionSize/2;
|
|
240
|
-
drawTextScreen(this.description, pos, descriptionSize, BLACK, 0, undefined, 'left', undefined, undefined, textWidth);
|
|
241
|
-
context.restore();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/** Render the icon for a medal
|
|
245
|
-
* @param {Vector2} pos - Screen space position
|
|
246
|
-
* @param {number} size - Screen space size
|
|
247
|
-
*/
|
|
248
|
-
renderIcon(pos, size)
|
|
249
|
-
{
|
|
250
|
-
// draw the image or icon
|
|
251
|
-
if (this.image)
|
|
252
|
-
mainContext.drawImage(this.image, pos.x-size/2, pos.y-size/2, size, size);
|
|
253
|
-
else
|
|
254
|
-
drawTextScreen(this.icon, pos, size*.7, BLACK);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
260
|
-
// Medals setting setters
|
|
261
|
-
|
|
262
|
-
/** Set how long to show medals for in seconds
|
|
263
|
-
* @param {number} time
|
|
264
|
-
* @memberof Settings */
|
|
265
|
-
function setMedalDisplayTime(time) { medalDisplayTime = time; }
|
|
266
|
-
|
|
267
|
-
/** Set how quickly to slide on/off medals in seconds
|
|
268
|
-
* @param {number} time
|
|
269
|
-
* @memberof Settings */
|
|
270
|
-
function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
271
|
-
|
|
272
|
-
/** Set size of medal display
|
|
273
|
-
* @param {Vector2} size
|
|
274
|
-
* @memberof Settings */
|
|
275
|
-
function setMedalDisplaySize(size) { medalDisplaySize = size.copy(); }
|
|
276
|
-
|
|
277
|
-
/** Set to stop medals from being unlockable
|
|
278
|
-
* @param {boolean} preventUnlock
|
|
279
|
-
* @memberof Settings */
|
|
280
|
-
function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
|
|
1
|
+
/**
|
|
2
|
+
* LittleJS Medal System
|
|
3
|
+
* - Achievement/trophy system for games
|
|
4
|
+
* - Medal class with name, description, icon, and unlock tracking
|
|
5
|
+
* - Automatic saving to local storage
|
|
6
|
+
* - Visual display queue with slide-in notifications
|
|
7
|
+
* - Newgrounds API integration for online achievements
|
|
8
|
+
* - Debug mode to unlock/reset medals during development
|
|
9
|
+
* @namespace Medals
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
let debugMedals = false;
|
|
15
|
+
|
|
16
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
17
|
+
// Medals settings
|
|
18
|
+
|
|
19
|
+
/** How long to show medals for in seconds
|
|
20
|
+
* @type {number}
|
|
21
|
+
* @default
|
|
22
|
+
* @memberof Settings */
|
|
23
|
+
let medalDisplayTime = 5;
|
|
24
|
+
|
|
25
|
+
/** How quickly to slide on/off medals in seconds
|
|
26
|
+
* @type {number}
|
|
27
|
+
* @default
|
|
28
|
+
* @memberof Settings */
|
|
29
|
+
let medalDisplaySlideTime = .5;
|
|
30
|
+
|
|
31
|
+
/** Size of medal display
|
|
32
|
+
* @type {Vector2}
|
|
33
|
+
* @default Vector2(640,80)
|
|
34
|
+
* @memberof Settings */
|
|
35
|
+
let medalDisplaySize = vec2(640, 80);
|
|
36
|
+
|
|
37
|
+
/** Set to stop medals from being unlockable (like if cheats are enabled)
|
|
38
|
+
* @type {boolean}
|
|
39
|
+
* @default
|
|
40
|
+
* @memberof Settings */
|
|
41
|
+
let medalsPreventUnlock = false;
|
|
42
|
+
|
|
43
|
+
/** List of all medals
|
|
44
|
+
* @type {Object}
|
|
45
|
+
* @memberof Medals */
|
|
46
|
+
const medals = {};
|
|
47
|
+
|
|
48
|
+
// Engine internal variables not exposed to documentation
|
|
49
|
+
let medalsDisplayQueue = [], medalsSaveName, medalsDisplayTimeLast;
|
|
50
|
+
|
|
51
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
52
|
+
|
|
53
|
+
/** Initialize medals with a save name used for storage
|
|
54
|
+
* - Call this after creating all medals
|
|
55
|
+
* - Checks if medals are unlocked
|
|
56
|
+
* @param {string} saveName
|
|
57
|
+
* @memberof Medals */
|
|
58
|
+
function medalsInit(saveName)
|
|
59
|
+
{
|
|
60
|
+
// check if medals are unlocked
|
|
61
|
+
medalsSaveName = saveName;
|
|
62
|
+
if (!debugMedals)
|
|
63
|
+
{
|
|
64
|
+
let saved = {};
|
|
65
|
+
try { saved = JSON.parse(localStorage[saveName] || '{}'); }
|
|
66
|
+
catch (e) { saved = {}; }
|
|
67
|
+
medalsForEach(medal => {
|
|
68
|
+
medal.unlocked = !!(saved[medal.id] && saved[medal.id].unlocked);
|
|
69
|
+
});
|
|
70
|
+
medalsSave();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// engine automatically renders medals
|
|
74
|
+
engineAddPlugin(undefined, medalsRender);
|
|
75
|
+
|
|
76
|
+
// plugin functions
|
|
77
|
+
function medalsRender()
|
|
78
|
+
{
|
|
79
|
+
if (!medalsDisplayQueue.length) return;
|
|
80
|
+
|
|
81
|
+
// update first medal in queue
|
|
82
|
+
const medal = medalsDisplayQueue[0];
|
|
83
|
+
const time = timeReal - medalsDisplayTimeLast;
|
|
84
|
+
if (!medalsDisplayTimeLast)
|
|
85
|
+
medalsDisplayTimeLast = timeReal;
|
|
86
|
+
else if (time > medalDisplayTime)
|
|
87
|
+
{
|
|
88
|
+
medalsDisplayTimeLast = 0;
|
|
89
|
+
medalsDisplayQueue.shift();
|
|
90
|
+
}
|
|
91
|
+
else
|
|
92
|
+
{
|
|
93
|
+
// slide on/off medals
|
|
94
|
+
const slideOffTime = medalDisplayTime - medalDisplaySlideTime;
|
|
95
|
+
const hidePercent =
|
|
96
|
+
time < medalDisplaySlideTime ? 1 - time / medalDisplaySlideTime :
|
|
97
|
+
time > slideOffTime ? (time - slideOffTime) / medalDisplaySlideTime : 0;
|
|
98
|
+
medal.render(hidePercent);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @callback MedalCallbackFunction - Function that processes a medal
|
|
105
|
+
* @param {Medal} medal
|
|
106
|
+
* @memberof Medals
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
/** Calls a function for each medal
|
|
110
|
+
* @param {MedalCallbackFunction} callback
|
|
111
|
+
* @memberof Medals */
|
|
112
|
+
function medalsForEach(callback)
|
|
113
|
+
{ Object.values(medals).forEach(medal=>callback(medal)); }
|
|
114
|
+
|
|
115
|
+
/** Reset all medals to locked and persist the cleared catalog
|
|
116
|
+
* @memberof Medals */
|
|
117
|
+
function medalsReset()
|
|
118
|
+
{
|
|
119
|
+
medalsForEach(medal => medal.unlocked = false);
|
|
120
|
+
medalsSave();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function medalsSave()
|
|
124
|
+
{
|
|
125
|
+
if (!medalsSaveName) return;
|
|
126
|
+
const data = {};
|
|
127
|
+
medalsForEach(medal => {
|
|
128
|
+
const entry = {
|
|
129
|
+
name: medal.name,
|
|
130
|
+
description: medal.description,
|
|
131
|
+
icon: medal.icon,
|
|
132
|
+
unlocked: medal.unlocked,
|
|
133
|
+
};
|
|
134
|
+
if (medal.image) entry.src = medal.image.src;
|
|
135
|
+
data[medal.id] = entry;
|
|
136
|
+
});
|
|
137
|
+
localStorage[medalsSaveName] = JSON.stringify(data);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Medal - Tracks an unlockable medal
|
|
144
|
+
* @memberof Medals
|
|
145
|
+
* @example
|
|
146
|
+
* // create a medal
|
|
147
|
+
* const medal_example = new Medal(0, 'Example Medal', 'More info about the medal goes here.', '🎖️');
|
|
148
|
+
*
|
|
149
|
+
* // initialize medals
|
|
150
|
+
* medalsInit('Example Game');
|
|
151
|
+
*
|
|
152
|
+
* // unlock the medal
|
|
153
|
+
* medal_example.unlock();
|
|
154
|
+
*/
|
|
155
|
+
class Medal
|
|
156
|
+
{
|
|
157
|
+
/** Create a medal object and adds it to the list of medals
|
|
158
|
+
* @param {number} id - The unique identifier of the medal
|
|
159
|
+
* @param {string} name - Name of the medal
|
|
160
|
+
* @param {string} [description] - Description of the medal
|
|
161
|
+
* @param {string} [icon] - Icon for the medal
|
|
162
|
+
* @param {string} [src] - Image location for the medal
|
|
163
|
+
*/
|
|
164
|
+
constructor(id, name, description='', icon='🏆', src)
|
|
165
|
+
{
|
|
166
|
+
ASSERT(id >= 0 && !medals[id]);
|
|
167
|
+
|
|
168
|
+
/** @property {number} - The unique identifier of the medal */
|
|
169
|
+
this.id = id;
|
|
170
|
+
|
|
171
|
+
/** @property {string} - Name of the medal */
|
|
172
|
+
this.name = name;
|
|
173
|
+
|
|
174
|
+
/** @property {string} - Description of the medal */
|
|
175
|
+
this.description = description;
|
|
176
|
+
|
|
177
|
+
/** @property {string} - Icon for the medal */
|
|
178
|
+
this.icon = icon;
|
|
179
|
+
|
|
180
|
+
/** @property {boolean} - Is the medal unlocked? */
|
|
181
|
+
this.unlocked = false;
|
|
182
|
+
|
|
183
|
+
/** @property {HTMLImageElement|undefined} - Source image for the medal icon, if any */
|
|
184
|
+
this.image = undefined;
|
|
185
|
+
if (src)
|
|
186
|
+
(this.image = new Image).src = src;
|
|
187
|
+
|
|
188
|
+
// add this to list of medals
|
|
189
|
+
medals[id] = this;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Unlocks a medal if not already unlocked */
|
|
193
|
+
unlock()
|
|
194
|
+
{
|
|
195
|
+
if (medalsPreventUnlock || this.unlocked) return;
|
|
196
|
+
|
|
197
|
+
ASSERT(medalsSaveName, 'save name must be set');
|
|
198
|
+
this.unlocked = true;
|
|
199
|
+
medalsSave();
|
|
200
|
+
medalsDisplayQueue.push(this);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** Render a medal
|
|
204
|
+
* @param {number} [hidePercent] - How much to slide the medal off screen
|
|
205
|
+
*/
|
|
206
|
+
render(hidePercent=0)
|
|
207
|
+
{
|
|
208
|
+
const context = mainContext;
|
|
209
|
+
const width = min(medalDisplaySize.x, mainCanvasSize.x);
|
|
210
|
+
const height = medalDisplaySize.y;
|
|
211
|
+
const x = mainCanvasSize.x - width;
|
|
212
|
+
const y = -height*hidePercent;
|
|
213
|
+
const backgroundColor = hsl(0,0,.9);
|
|
214
|
+
|
|
215
|
+
// draw containing rect and clip to that region
|
|
216
|
+
context.save();
|
|
217
|
+
context.beginPath();
|
|
218
|
+
context.fillStyle = backgroundColor.toString();
|
|
219
|
+
context.strokeStyle = BLACK.toString();
|
|
220
|
+
context.lineWidth = 3;
|
|
221
|
+
context.rect(x, y, width, height);
|
|
222
|
+
context.fill();
|
|
223
|
+
context.stroke();
|
|
224
|
+
context.clip();
|
|
225
|
+
|
|
226
|
+
// draw the icon
|
|
227
|
+
const gap = vec2(.1, .05).scale(height);
|
|
228
|
+
const medalDisplayIconSize = height - 2*gap.x;
|
|
229
|
+
this.renderIcon(vec2(x + gap.x + medalDisplayIconSize/2, y + height/2), medalDisplayIconSize);
|
|
230
|
+
|
|
231
|
+
// draw the name
|
|
232
|
+
const nameSize = height*.5;
|
|
233
|
+
const descriptionSize = height*.3;
|
|
234
|
+
const pos = vec2(x + medalDisplayIconSize + 2*gap.x, y + gap.y*2 + nameSize/2);
|
|
235
|
+
const textWidth = width - medalDisplayIconSize - 3*gap.x;
|
|
236
|
+
drawTextScreen(this.name, pos, nameSize, BLACK, 0, undefined, 'left', undefined, undefined, textWidth);
|
|
237
|
+
|
|
238
|
+
// draw the description
|
|
239
|
+
pos.y = y + height - gap.y*2 - descriptionSize/2;
|
|
240
|
+
drawTextScreen(this.description, pos, descriptionSize, BLACK, 0, undefined, 'left', undefined, undefined, textWidth);
|
|
241
|
+
context.restore();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Render the icon for a medal
|
|
245
|
+
* @param {Vector2} pos - Screen space position
|
|
246
|
+
* @param {number} size - Screen space size
|
|
247
|
+
*/
|
|
248
|
+
renderIcon(pos, size)
|
|
249
|
+
{
|
|
250
|
+
// draw the image or icon
|
|
251
|
+
if (this.image)
|
|
252
|
+
mainContext.drawImage(this.image, pos.x-size/2, pos.y-size/2, size, size);
|
|
253
|
+
else
|
|
254
|
+
drawTextScreen(this.icon, pos, size*.7, BLACK);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
260
|
+
// Medals setting setters
|
|
261
|
+
|
|
262
|
+
/** Set how long to show medals for in seconds
|
|
263
|
+
* @param {number} time
|
|
264
|
+
* @memberof Settings */
|
|
265
|
+
function setMedalDisplayTime(time) { medalDisplayTime = time; }
|
|
266
|
+
|
|
267
|
+
/** Set how quickly to slide on/off medals in seconds
|
|
268
|
+
* @param {number} time
|
|
269
|
+
* @memberof Settings */
|
|
270
|
+
function setMedalDisplaySlideTime(time) { medalDisplaySlideTime = time; }
|
|
271
|
+
|
|
272
|
+
/** Set size of medal display
|
|
273
|
+
* @param {Vector2} size
|
|
274
|
+
* @memberof Settings */
|
|
275
|
+
function setMedalDisplaySize(size) { medalDisplaySize = size.copy(); }
|
|
276
|
+
|
|
277
|
+
/** Set to stop medals from being unlockable
|
|
278
|
+
* @param {boolean} preventUnlock
|
|
279
|
+
* @memberof Settings */
|
|
280
|
+
function setMedalsPreventUnlock(preventUnlock) { medalsPreventUnlock = preventUnlock; }
|