Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
citius-invaders
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomás Teijeiro Campo
citius-invaders
Commits
bf4f385b
Commit
bf4f385b
authored
Jun 16, 2016
by
Pablo R. Mier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Basic game with evolution implemented
parent
a6dd0b9c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
153 additions
and
45 deletions
+153
-45
Game.js
Game.js
+92
-37
index.html
index.html
+1
-0
js/Evolution.js
js/Evolution.js
+50
-3
js/Invader.js
js/Invader.js
+5
-0
js/Player.js
js/Player.js
+3
-3
settings.json
settings.json
+2
-2
No files found.
Game.js
View file @
bf4f385b
...
...
@@ -5,7 +5,7 @@ var DIR_CHANGE_MIN_TIME = 10;
var
SHOOT_DELAY
=
100
;
var
MIN_INVADERS
=
4
;
var
INITIAL_INVADERS
=
6
;
var
MIN_GENERATION_TIME
=
Phaser
.
Time
.
SECOND
*
2
;
var
MIN_GENERATION_TIME
=
Phaser
.
Time
r
.
SECOND
*
2
;
invadersApp
.
Game
=
function
(
game
)
{
...
...
@@ -40,7 +40,6 @@ invadersApp.Game = function (game) {
this
.
lastShootAt
=
0
;
this
.
readyToFire
=
true
;
this
.
currentGenerationTime
=
Phaser
.
Time
.
SECOND
*
5
;
};
invadersApp
.
Game
.
prototype
=
{
...
...
@@ -49,6 +48,10 @@ invadersApp.Game.prototype = {
var
that
=
this
;
this
.
currentGenerationTime
=
Phaser
.
Timer
.
SECOND
*
5
;
this
.
currentGeneration
=
0
;
this
.
lastGenerationTime
=
this
.
game
.
time
.
now
;
// Load game config
this
.
settings
=
this
.
game
.
cache
.
getJSON
(
'
settings
'
);
...
...
@@ -61,28 +64,12 @@ invadersApp.Game.prototype = {
this
.
objects
.
invaders
.
physicsBodyType
=
Phaser
.
Physics
.
ARCADE
;
// Initialize
this
.
objects
.
invaders
=
[];
for
(
var
i
=
0
;
i
<
INITIAL_INVADERS
;
i
++
)
this
.
objects
.
invaders
.
push
(
new
invadersApp
.
Invader
(
this
));
for
(
var
i
=
0
;
i
<
INITIAL_INVADERS
;
i
++
)
this
.
objects
.
invaders
.
add
(
new
invadersApp
.
Invader
(
this
));
this
.
player
=
new
invadersApp
.
Player
(
this
);
this
.
game
.
add
.
existing
(
this
.
player
);
// create a new bitmap data object
var
wallBmp
=
this
.
game
.
add
.
bitmapData
(
this
.
game
.
width
,
3
);
// draw the wall
wallBmp
.
ctx
.
beginPath
();
wallBmp
.
ctx
.
rect
(
0
,
0
,
this
.
game
.
width
,
3
);
wallBmp
.
ctx
.
fillStyle
=
'
#ffffff
'
;
wallBmp
.
ctx
.
fill
();
// use the bitmap data as the texture for the sprite
this
.
wall
=
this
.
add
.
sprite
(
0
,
this
.
game
.
height
-
WALL_MARGIN
,
wallBmp
);
this
.
game
.
physics
.
enable
(
this
.
wall
,
Phaser
.
Physics
.
ARCADE
);
this
.
wall
.
body
.
immovable
=
true
;
this
.
createWall
();
this
.
cursors
=
this
.
game
.
input
.
keyboard
.
createCursorKeys
();
this
.
fireButton
=
this
.
game
.
input
.
keyboard
.
addKey
(
Phaser
.
Keyboard
.
SPACEBAR
);
...
...
@@ -98,33 +85,40 @@ invadersApp.Game.prototype = {
this
.
game
.
paused
=
true
;
//this.pausePhysics();
// New generation event, check for every second
this
.
game
.
time
.
events
.
loop
(
Phaser
.
Timer
.
SECOND
,
this
.
createGeneration
,
this
);
// Gargabe collect killed invaders. If the invaders are
// destroyed on a bullet hit, it may produce an exception
// from physics module if there is a concurrent collision
// detection going on
this
.
game
.
time
.
events
.
loop
(
Phaser
.
Timer
.
SECOND
*
5
,
function
()
{
this
.
objects
.
invaders
.
forEachDead
(
function
(
invader
)
{
invader
.
destroy
();
},
this
);
},
this
);
},
update
:
function
()
{
// If physics are paused, skip all
if
(
this
.
game
.
physics
.
arcade
.
isPaused
)
return
;
var
that
=
this
;
this
.
game
.
physics
.
arcade
.
overlap
(
this
.
player
.
bullets
,
this
.
objects
.
invaders
,
function
(
invader
,
bullet
)
{
// If physics are paused, skip all
// if (this.game.physics.arcade.isPaused) return;
this
.
game
.
physics
.
arcade
.
collide
(
this
.
wall
,
this
.
objects
.
invaders
);
this
.
game
.
physics
.
arcade
.
overlap
(
this
.
player
.
bullets
,
this
.
objects
.
invaders
,
function
(
bullet
,
invader
)
{
bullet
.
kill
();
var
alive
=
that
.
objects
.
invaders
.
filter
(
function
(
invader
)
{
return
invader
.
alive
;
}).
length
;
if
(
alive
>
MIN_INVADERS
){
invader
.
kill
();
}
else
{
that
.
objects
.
invaders
.
forEach
(
function
(
invader
)
{
invader
.
showField
(
true
);
});
var
living
=
that
.
objects
.
invaders
.
countLiving
();
if
(
living
>
MIN_INVADERS
)
invader
.
kill
();
if
(
living
==
MIN_INVADERS
+
1
)
{
that
.
objects
.
invaders
.
forEachAlive
(
function
(
invader
)
{
invader
.
showField
();
},
that
);
}
},
null
,
this
);
this
.
game
.
physics
.
arcade
.
collide
(
this
.
wall
,
this
.
objects
.
invaders
);
},
quitGame
:
function
(
pointer
)
{
...
...
@@ -139,6 +133,67 @@ invadersApp.Game.prototype = {
pausePhysics
:
function
(
pause
)
{
if
(
pause
==
undefined
)
pause
=
true
;
this
.
game
.
physics
.
arcade
.
isPaused
=
pause
;
},
createGeneration
:
function
()
{
var
that
=
this
;
if
(
this
.
game
.
time
.
now
>
this
.
lastGenerationTime
+
this
.
currentGenerationTime
)
{
this
.
lastGenerationTime
=
this
.
game
.
time
.
now
;
// The number of invaders
var
alive
=
this
.
objects
.
invaders
.
countLiving
();
var
aliveInvaders
=
this
.
objects
.
invaders
.
filter
(
function
(
child
,
index
,
children
)
{
return
child
.
alive
;
},
true
);
aliveInvaders
.
callAll
(
'
increaseFitness
'
);
// The number of new individuals is determined by a box-cox
// transformation with lambda=0.6.
var
numPairs
=
Math
.
floor
((
Math
.
pow
(
alive
,
0.6
)
-
1
)
/
0.6
);
var
pool
=
invadersApp
.
evolution
.
pool
(
aliveInvaders
.
list
,
numPairs
);
var
offspring
=
invadersApp
.
evolution
.
evolve
(
pool
,
this
.
settings
.
genes
);
// Start an animation
// Draw a line https://codepen.io/codevinsky/pen/dAjDp
offspring
.
forEach
(
function
(
p
)
{
var
x
=
(
p
[
0
].
x
+
p
[
1
].
x
)
/
2
;
var
y
=
(
p
[
0
].
y
+
p
[
1
].
y
)
/
2
;
that
.
objects
.
invaders
.
add
(
new
invadersApp
.
Invader
(
that
,
p
[
2
],
x
,
y
));
});
this
.
currentGeneration
++
;
// Disable shields
aliveInvaders
.
callAll
(
'
showField
'
,
false
);
// Decrease next generation time
if
(
this
.
currentGenerationTime
>
MIN_GENERATION_TIME
)
{
this
.
currentGenerationTime
-=
150
;
console
.
log
(
this
.
currentGenerationTime
);
}
}
},
createWall
:
function
()
{
// create a new bitmap data object
var
wallBmp
=
this
.
game
.
add
.
bitmapData
(
this
.
game
.
width
,
3
);
// draw the wall
wallBmp
.
ctx
.
beginPath
();
wallBmp
.
ctx
.
rect
(
0
,
0
,
this
.
game
.
width
,
3
);
wallBmp
.
ctx
.
fillStyle
=
'
#ffffff
'
;
wallBmp
.
ctx
.
fill
();
// use the bitmap data as the texture for the sprite
this
.
wall
=
this
.
add
.
sprite
(
0
,
this
.
game
.
height
-
WALL_MARGIN
,
wallBmp
);
this
.
game
.
physics
.
enable
(
this
.
wall
,
Phaser
.
Physics
.
ARCADE
);
this
.
wall
.
body
.
immovable
=
true
;
}
};
index.html
View file @
bf4f385b
...
...
@@ -10,6 +10,7 @@
<script
src=
"js/Utils.js"
></script>
<script
src=
"js/Player.js"
></script>
<script
src=
"js/Invader.js"
></script>
<script
src=
"js/Evolution.js"
></script>
<script
src=
"MainMenu.js"
></script>
<script
src=
"Game.js"
></script>
</head>
...
...
js/Evolution.js
View file @
bf4f385b
...
...
@@ -5,10 +5,57 @@
var
invadersApp
=
invadersApp
||
{};
invadersApp
.
evolution
=
{
evolve
:
function
(
individuals
){
evolve
:
function
(
pool
,
genes
,
mutation
){
if
(
mutation
===
undefined
)
{
mutation
=
0.1
};
var
offspring
=
[];
pool
.
forEach
(
function
(
pair
)
{
var
p1
=
pair
[
0
];
var
p2
=
pair
[
1
];
var
children
=
[];
var
recombinate
=
function
(){
for
(
var
gen
in
genes
){
if
(
genes
.
hasOwnProperty
(
gen
))
{
var
gen1
=
p1
.
genes
[
gen
];
var
gen2
=
p2
.
genes
[
gen
];
var
min
=
(
gen1
<
gen2
)
?
gen1
:
gen2
;
var
max
=
(
gen1
>
gen2
)
?
gen1
:
gen2
;
children
[
gen
]
=
Math
.
random
()
*
(
max
-
min
)
+
min
;
if
(
Math
.
random
()
<
mutation
)
{
// Mutate this gene
children
[
gen
]
=
Math
.
random
()
*
(
genes
[
gen
].
max
-
genes
[
gen
].
min
)
+
genes
[
gen
].
min
;
}
}
}
offspring
.
push
([
p1
,
p2
,
children
]);
});
return
offspring
;
},
};
pool
:
function
(
population
,
size
){
var
pool
=
[];
while
(
pool
.
length
<
size
){
var
p1
=
this
.
binary_tournament
(
population
);
// Copy and remove the selected invader
var
pop2
=
population
.
slice
(
0
);
pop2
.
splice
(
pop2
.
indexOf
(
p1
),
1
);
var
p2
=
this
.
binary_tournament
(
pop2
);
pool
.
push
([
p1
,
p2
]);
}
return
pool
;
},
binary_tournament
:
function
(
population
){
var
invader1
=
this
.
pick
(
population
);
var
invader2
=
this
.
pick
(
population
);
if
(
invader1
.
fitness
>
invader2
.
fitness
)
{
return
invader1
;
}
else
{
return
invader2
;
}
},
pick
:
function
(
array
){
return
array
[
Math
.
floor
(
Math
.
random
()
*
array
.
length
)];
}
};
\ No newline at end of file
js/Invader.js
View file @
bf4f385b
...
...
@@ -34,6 +34,8 @@ invadersApp.Invader = function (ctx, genes, x, y) {
// Used to control the probability of x-y change in direction
this
.
lastTimeChanged
=
0
;
this
.
fitness
=
0
;
// Create a shield
var
shield
=
this
.
game
.
make
.
graphics
(
0
,
0
);
shield
.
lineStyle
(
1
,
0x15AFF0
,
1
);
...
...
@@ -76,3 +78,6 @@ invadersApp.Invader.prototype.freeze = function (freeze) {
this
.
body
.
velocity
.
y
=
this
.
genes
[
'
yvelocity
'
];
}
};
invadersApp
.
Invader
.
prototype
.
increaseFitness
=
function
()
{
this
.
fitness
++
;
};
js/Player.js
View file @
bf4f385b
...
...
@@ -42,13 +42,13 @@ invadersApp.Player.prototype.update = function () {
if
(
this
.
scale
.
x
>
0
){
this
.
scale
.
x
*=
-
1
;
}
this
.
body
.
velocity
.
x
=
-
25
0
;
this
.
body
.
velocity
.
x
=
-
50
0
;
}
else
if
(
this
.
ctx
.
cursors
.
right
.
isDown
)
{
if
(
this
.
scale
.
x
<
0
){
this
.
scale
.
x
*=
-
1
;
}
this
.
body
.
velocity
.
x
=
25
0
;
this
.
body
.
velocity
.
x
=
50
0
;
}
...
...
@@ -68,7 +68,7 @@ invadersApp.Player.prototype.update = function () {
xpos
=
this
.
x
+
21
;
}
bullet
.
reset
(
xpos
,
this
.
y
-
20
);
bullet
.
body
.
velocity
.
y
=
-
12
00
;
bullet
.
body
.
velocity
.
y
=
-
20
00
;
}
}
}
...
...
settings.json
View file @
bf4f385b
...
...
@@ -11,11 +11,11 @@
},
"xvelocity"
:
{
"min"
:
0
,
"max"
:
15
0
"max"
:
30
0
},
"yvelocity"
:
{
"min"
:
0
,
"max"
:
15
0
"max"
:
30
0
},
"x_prob_change_dir"
:
{
"min"
:
0.00
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment