/
De_Schatzoeker.html
431 lines (353 loc) · 18.4 KB
/
De_Schatzoeker.html
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Phaser - Making your first game, part 9</title>
<script type="text/javascript" src="js/phaser.min.js"></script>
<script type="text/javascript" src="js/Gamygdala.js"></script>
<script type="text/javascript" src="js/GamygdalaPhaserPlugins.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
Leon = function(){
//simply create the namespace
};
Leon.Map = function (game, w, h, tileImages, tileImageSize) {
this.TILESIZE=35;
this.TILEIMAGESIZE=tileImageSize;
this.game = game;
this.w = w;
this.h = h;
this.tiles=new Array(h);
this.damage=new Array(h);
this.tileImages=tileImages;
for (var y=0;y<this.h;y++){
this.tiles[y]=new Array(w);
this.damage[y]=new Array(w);
for (var x=0;x<this.w;x++){
this.tiles[y][x]=-1;
this.damage[y][x]=false;
}
}
};
Leon.Map.prototype.setLevel = function(lvlData){
for (var y=0;y<this.h;y++){
for (var x=0;x<this.w;x++){
this.tiles[y][x]=lvlData[y][x];
switch (lvlData[y][x]){
case 73:
case 85:
case 61:
this.damage[y][x]=true;
break;
default:
this.damage[y][x]=false;
break;
}
}
}
};
Leon.Map.prototype.setTile = function(x,y,nr,dmg){
this.tiles[y][x]=nr;
this.damage[y][x]=dmg;
};
Leon.Map.prototype.createMap = function(){
// The platforms group contains the tiles
this.ground = this.game.add.group();
this.hitables = this.game.add.group();
// We will enable physics for any object that is created in this group
this.ground.enableBody = true;
this.hitables.enableBody = true;
for (var y=0;y<this.h;y++){
for (var x=0;x<this.w;x++){
// Here we create the ground.
var tile;
if (this.tiles[y][x]!=-1){
if (this.damage[y][x]==false){
tile = this.ground.create(x*this.TILESIZE, y*this.TILESIZE, this.tileImages, this.tiles[y][x]);
} else
{ tile = this.hitables.create(x*this.TILESIZE, y*this.TILESIZE, this.tileImages, this.tiles[y][x]);
}
tile.scale.x=this.TILESIZE/this.TILEIMAGESIZE;
tile.scale.y=this.TILESIZE/this.TILEIMAGESIZE;
tile.body.immovable = true;
}
}
}
};
var game = new Phaser.Game(700, 560, Phaser.AUTO, '', { preload: preload, create: create, update: update });
function preload() {
game.load.image('sky', 'assets/sky.png');
game.load.spritesheet('tiles', 'assets/tiles.png', 70, 70);
game.load.image('star', 'assets/star.png');
game.load.spritesheet('dude', 'assets/dude.png', 32, 48);
//The needed graphics for the bad guys and the lifebar
game.load.spritesheet('badguy','assets/baddie.png', 32, 32);
game.load.image('life', 'assets/life.png')
//This line is needed for the Gamygdala.Expression plugin, if you make your own emotion expressions and effects, this is not needed.
game.load.spritesheet('emotions', 'assets/emotions.png', 256, 256);
}
var player;
var bad_guys=[];
var platforms;
var cursors;
var map;
var stars;
var lifes;
var score = 0;
var scoreText;
var hitTimer=0;
var NR_OF_STARS=6;
var NR_OF_BAD_GUYS=2;
//For the Gamygdala based emotions: define the main appraisal engine reference
var emotionEngine;
function create() {
// We're going to be using physics, so enable the Arcade Physics system
game.physics.startSystem(Phaser.Physics.ARCADE);
//game.input.keyboard.addKeys({ 'up': Phaser.Keyboard.SPACEBAR, 'down': Phaser.Keyboard.DOWN, 'left': Phaser.Keyboard.LEFT, 'right': Phaser.Keyboard.RIGHT });
// A simple background for our game
game.add.sprite(0, 0, 'sky');
map = new Leon.Map(game, 20, 16 , 'tiles', 70);
map.setLevel([
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,105,95,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[105,83,107,95,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[49,49,69,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[49,49,81,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,85,73,61,-1,-1,-1,-1],
[ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
]);
map.createMap();
// The player and its settings
player = game.add.sprite(32, 0, 'dude');
// We need to enable physics on the player
game.physics.arcade.enable(player);
// Player physics properties. Give the little guy a slight bounce.
player.body.bounce.y = .2;
player.body.gravity.y = 300;
player.body.collideWorldBounds = true;
// Our two animations, walking left and right.
player.animations.add('left', [0, 1, 2, 3], 10, true);
player.animations.add('right', [5, 6, 7, 8], 10, true);
player.animations.add('hit', [2, 4, 5], 20, true);
//Do the same we did for the player but now for all bad guys
bad_guys = game.add.group();
bad_guys.enableBody = true;
game.physics.arcade.enable(bad_guys);
for (var i=0;i<NR_OF_BAD_GUYS;i++){
var bad_guy= bad_guys.create(400+i*100, game.world.height - 300, 'badguy');
bad_guy.body.bounce.y = 0.2*i+0.2;
bad_guy.body.gravity.y = 300;
bad_guy.body.collideWorldBounds = true;
bad_guy.animations.add('left',[0,1],10,true);
bad_guy.animations.add('right',[2,3],10,true);
}
// Finally some stars to collect
stars = game.add.group();
// We will enable physics for any star that is created in this group
stars.enableBody = true;
// Here we'll create NR_OF_STARS of them evenly spaced apart
for (var i = 0; i < NR_OF_STARS; i++)
{
// Create a star inside of the 'stars' group
var star = stars.create(i * 800/NR_OF_STARS, 0, 'star');
// Let gravity do its thing
star.body.gravity.y = 300;
// This just gives each star a slightly random bounce value
star.body.bounce.y = 0.7 + Math.random() * 0.2;
}
//Now add the life bar
lifes = game.add.group();
for (var i=0;i<3;i++)
{ lifes.create(16+i*32,50,'life');
}
// The score
scoreText = game.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });
// Our controls.
cursors = game.input.keyboard.createCursorKeys();
//Here we come to the emotion part. This explains the use of the Gamygdala emotion engine as published in IEEE Transaction on Affective Computing, 4(1)
//Note that the plugin part is Phaser specific, and not needed if you don't use phaser
//First create the main emotion engine (using the Phaser plugin wrapper class, but this can be done directly too, see below).
//The engine is needed to interpret how events (Belief in Gamygdala terms) relate to goals resulting in emotions.
//The following three lines create one instance of Gamygdala that is used by all emotionAgents, and registers this as a Phaser plugin
//If you don't need emotional decay (the fact that emotions decay,i.e., if a guy is angry he will slowly become less angry) to be managed by the Phaser plugin engine,
//then you don't need to do all this, instead you can do the following (commented):
//emotionEngine=new TUDelft.Gamygdala(); //this simply creates an emotion engine without plugin support.
gamygdalaPlugin=new Phaser.Plugin.GamygdalaWrapper();//create the Phaser plugin.
game.plugins.add(gamygdalaPlugin);//add the plugin to the game, as required by Phaser
emotionEngine=gamygdalaPlugin.getGamygdala(); //this gives you a ref to the actual underlying emotion engine, so that you can do what you need to do.
//From now on we can do everything we need with the emotionEngine object reference, as this is an object of type Gamygdala
//create a new agent that represents the players emotional state. The method createAgent makes a new Agent, and registers it with gamygdala, and returns a ref to the agent.
//We store the ref in the Phaser player object for later convenience.
player.emotionAgent=emotionEngine.createAgent('player');
//give the player some goals: survival and winning are both good, but survival is better.
emotionEngine.createGoalForAgent('player','survive', 1);
emotionEngine.createGoalForAgent('player','win', 0.7);
//Alternatively, you can do the necessary goal magamenet yourself instead of having gamygdala do it for you with the create method.
//This involves creating the goals and adding them to the agent(s) that have these goals (there can be more owners of the same goal so you can create group goals), and registering the goal to gamygdala.
//player.emotionAgent.addGoal(new TUDelft.Gamygdala.Goal('survive', 1));
//player.emotionAgent.addGoal(new TUDelft.Gamygdala.Goal('win', 0.7));
//emotionEngine.registerGoal(player.emotionAgent.getGoalByName('survive'));
//emotionEngine.registerGoal(player.emotionAgent.getGoalByName('win'));
//Now we are basically done for the player's emotions, apart from the fact we want to see something, so we add expression to the player.
//This is not really part of Gamygdala, just an easy and crude way of visualizing the emotions using Phaser
//game.plugins.add(new Phaser.Plugin.GamygdalaExpression(game, player, player.emotionAgent));
//We are now done with setting up the player, but we want the monsters to be emotional guys too (to showcase relations NPC's can have with other NPC's or player agents)
for (var i=0;i<bad_guys.countLiving();i++)
{ //create the Gamygdala agent and store it in the bad_guy object for easy reference later, because when the player gets hit, we need to tell gamygdala who did it.
bad_guys.getAt(i).emotionAgent=emotionEngine.createAgent('monster'+i);
//add a relation between player and monster for fun, the first monster hates the player, the second one likes the player, the third hates, etc..
emotionEngine.createRelation('monster'+i, 'player',(i%2)*2-1);
//add expression to the bad guy so we see something
//game.plugins.add(new Phaser.Plugin.GamygdalaExpression(game, bad_guys.getAt(i), bad_guys.getAt(i).emotionAgent));
//note that we don't need to configure goals for these bad guys. They don't need to want to achieve something themselves to have social emotions, they can still feel pity, gloating, etc.. simply due to what happens to the player.
}
//Finally we need to tell gamygdala to decay emotional states over time (you don't stay angry, the intensity should go down right?)
//There are three ways to do emotional decay:
//1. Either you use Gamygdala as standalone module, not requiring Phaser.
// In this case , Gamygdala will manage the emotional decay itself, and you need to tell it to do so.
// In the following line, you tell Gamygdala that every 100 Millis it decays the emotional state of all agents (using the default exponential decay with a factor of 0.8 per second).
//emotionEngine.startDecay(100);
//2. You use the phaser plugin update to manage emotional decay, you should tell the plugin to do so using the next line.
gamygdalaPlugin.phaserManagedDecay=true;
//3. Finally, you can choose to call emotionEngine.decayAll() yourself when you need it.
// This is usefull if you have a lot of agents and need to be efficient, or, if some agents dont need decay at all, or you want to write your own timing routines
// In such a case you need to manage decay yourself using the desired timing, so you have to manage the interval yourself.
//Alternatively, you can set the type (exponential or linear) and speed of decay [0..1], for example with a faster exp decay speed using:
//emotionEngine.setDecay(0.4, emotionEngine.exponentialDecay);
//Now you need to calibrate the overall emotional intensity. This is more an art than a science.
//If you notice the emotional intensities are too low in general, you set the gain higher, otherwise you set it lower. Gain must be between 0 and 20
//How gain works can be seen in the Agent.getEmotionalState();
//Normally, you decide the gain for the whole game, but if you know that certain NPC's need a higher or lower one, you can set the gain for each NPC separately using Agent.setGain(gainFactor);
emotionEngine.setGain(10);
//If you want to enable debug output to the console, than uncomment the next line
//emotionEngine.debug=true;
//Some notes: Gamygdala is very flexible. You can make use of it in many different ways, and this example is only one way. For example, the degree of agent specific emotion control is flexible.
//To name a few ways in which you can do this:
// You can choose to run the engine for only those agents you know have received new beliefs (using Gamygdala.appraise(Belief, Agent), where Agent is the one for whom you appraise the belief)
// Define a common goal for multiple agents so that they all react to beliefs that changes the goal likelyhood of being achieved.
// You can define completely different dynamics for each agent, using different decayfunctions and decay factors
// You can have only one "agent" for all bad guys, e.g., an agent called "bad_guys", if you want them to be all bad, with the same relation. Then being hit simply results in an event caused by "bad_guys", and you can then use that same agent ref for all expressions for the bad guys.
//Also notice that Gamygdala's classes use String references in the constructors, e.g., new Belief(likelihood, causalAgentName, affectedGoalNames, goalCongruences).
//This is true for new Agent(name), new Goal(name, utility), new Relation(...) and newBelief(...). This makes is very is to script/config the emotional setup, because you can simply use string refs to the objects.
//Also the Gamygdala.createAgent(..) and Gamygdala.createGoalForAgent(..) work with literal refs, so an alternative is to have a sequence of these be loaded from a txt file and executed.
}
function update() {
// Collide the player and the stars with the platforms
game.physics.arcade.collide(player, map.ground);
game.physics.arcade.collide(player, map.hitables, hit, null, this);
game.physics.arcade.collide(stars, map.ground);
game.physics.arcade.collide(stars, map.hitables);
game.physics.arcade.collide(bad_guys, map.ground);
game.physics.arcade.collide(bad_guys, map.hitables);
// Checks to see if the player overlaps with any of the stars, if he does call the collectStar function
game.physics.arcade.overlap(player, stars, collectStar, null, this);
game.physics.arcade.collide(player, bad_guys, hit, null, this);
if (hitTimer<=0){
// Reset the players velocity (movement)
player.body.velocity.x = 0;
if (cursors.left.isDown)
{
// Move to the left
player.body.velocity.x = -150;
player.animations.play('left');
}
else if (cursors.right.isDown)
{
// Move to the right
player.body.velocity.x = 150;
player.animations.play('right');
}
else
{
// Stand still
player.animations.stop();
player.frame = 4;
}
// Allow the player to jump if they are touching the ground.
if (cursors.up.isDown && player.body.touching.down)
{
player.body.velocity.y = -350;
}
} else
hitTimer--;
//control the bad guys
for (var i=0;i<bad_guys.countLiving();i++){
var bad_guy=bad_guys.getAt(i);
var speed=20+10*i;
if (player.body.x+1 < bad_guy.body.x)
{ bad_guy.body.velocity.x=-speed;
bad_guy.animations.play('left');
} else if (player.body.x-1 > bad_guy.body.x)
{ bad_guy.body.velocity.x=speed;
bad_guy.animations.play('right');
} else if (bad_guy.body.touching.down)
{ bad_guy.body.velocity.x=0;
bad_guy.body.velocity.y=-speed*3;
bad_guy.animations.stop();
}
}
}
function collectStar (player, star) {
// Removes the star from the screen
star.kill();
// Add and update the score
score += 1;
scoreText.text = 'Score: ' + score;
//Add Emotion event, and simply call the main Gamygdala instance and ask it to appraise the event for all agent's it knows.
//in our case, eating a star is incrementally good for the agent's goal of winning, so we add a little bit of certainty towards reaching the goal.
emotionEngine.appraiseBelief(1,'player',['win'],[0.025], true);
//Alternatively you can appraise this belief solely from the player's perspective using the ref to the gamygdala agent you stored somewhere.
//This is equivalent in our case because we know that this event only affects goals the player owns.
//player.emotionAgent.appraise(new TUDelft.Gamygdala.Belief(1,'player',['win'],[score/10]));
if (score==NR_OF_STARS){
//Now we know we achieved the goal completely, so we tell gamygdala that something happened that completely satisfies our goal (not incrementally, but absolutely, i.e., congruence and likelihood=1)
emotionEngine.appraiseBelief(1,'player',['win'],[1]);
game.paused=true;
game.add.text(300, 300, 'YOU WIN :-)', { fontSize: '32px', fill: '#000' });
}
}
function hit (player, bad_guy) {
if (hitTimer<=0){
// Add and update lives
lifes.getFirstAlive().kill();
scoreText.text = 'Score: ' + score;
player.body.velocity.y = -150;
if (player.body.x < bad_guy.body.x)
player.body.velocity.x = -200;
else
player.body.velocity.x = 200;
player.animations.play('hit');
hitTimer=50;
//Add Emotion event, and simply call the main Gamygdala instance and ask it to appraise the event for all agent's it knows.
//in our case, being hit is bad for the player's goal of surviving the game.
//note that since each of our bad guys is a little different (some like the agent, some don't) we need to know which bad guy did it,
//which is why we stored the emotionAgent in the Phaser object and use it's name to tell Gamygdala who caused the event.
if (bad_guy.emotionAgent)
emotionEngine.appraiseBelief(1,bad_guy.emotionAgent.name,['survive'],[-0.34*lifes.countDead()]);
//Alternatively you can appraise the belief solely from the player's perspective using the ref to the gamygdala agent you stored somewhere.
//This is equivalent in our case because we know that this event only affects goals the player owns.
//player.emotionAgent.appraise(new TUDelft.Gamygdala.Belief(1,bad_guy.emotionAgent.name,['survive'],[-0.34*lifes.countDead()]));
if (lifes.countLiving()==0){
game.paused=true;
game.add.text(300, 300, 'YOU LOOSE :-(', { fontSize: '32px', fill: '#000' });
}
}
}
</script>
</body>
</html>