Skip to content

Instantly share code, notes, and snippets.

@rakuishi
Created December 28, 2019 04:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rakuishi/e0fbaaf3f6d433e830f1bd29794a0224 to your computer and use it in GitHub Desktop.
Save rakuishi/e0fbaaf3f6d433e830f1bd29794a0224 to your computer and use it in GitHub Desktop.
群れは意識をもつ 個の自由と集団の秩序
html, body {
margin: 0;
padding: 0;
}
.ant-box {
position: relative;
width: 400px;
height: 400px;
border: 1px solid #ddd;
}
.ant, .candy {
position: absolute;
width: 20px;
height: 20px;
font-size: 20px;
}
.candy {
background-color: #FD95FF;
}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="normalize.css" />
<link rel="stylesheet" href="index.css" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div class="ant-box">
<div v-for="candy in candies">
<candy v-bind:candy="candy" v-bind:key="candy.id" />
</div>
<div v-for="ant in ants">
<ant v-bind:ant="ant" v-bind:key="ant.id" />
</div>
</div>
<button v-on:click="proceed">Proceed</button>
</div>
<script src="index.js"></script>
</body>
</html>
/*
~ アリの大きさ 20px
~ ボックスの格子の数 20
~ アリは基本的に前回の進行方向を再利用しようとするが、1/6 の確率でランダムに方向を変える
~ 左上から時計回りに 0~7 の進行方向を保持する
~ 周囲 8 マスにアメがある場合はそちらに移動する
*/
Vue.component("ant", {
props: ["ant"],
template:
'<div class="ant" v-bind:style="{ top: 20 * ant.x, left: 20 * ant.y }">🐜</div>',
})
Vue.component("candy", {
props: ["candy"],
template:
'<div class="candy" v-bind:style="{ top: 20 * candy.x, left: 20 * candy.y }">🍬</div>',
})
var app = new Vue({
el: "#app",
data: {
ants: [],
candies: [],
},
created() {
this.setupPositions(this.candies, 10)
this.setupPositions(this.ants, 20)
},
methods: {
setupPositions(objects, length) {
while (objects.length < length) {
let x = this.getRandomPosition()
let y = this.getRandomPosition()
const result = objects.filter(position => position.x == x && position.y == y)
if (result.length != 0) continue
objects.push({ id: objects.length, x: x, y: y })
}
},
getRandomPosition() {
return Math.floor(Math.random() * 20)
},
calculateAntsBehavior(ant) {
if (this.isEatingCandy(ant))
return
let candy = this.getNearbyCandy(ant)
if (candy != null && this.isEmpty(candy.x, candy.y)) {
ant.x = candy.x
ant.y = candy.y
return
}
if (ant.vector == undefined || (ant.vector && Math.floor(Math.random() * 6) == 0)) {
ant.vector = Math.floor(Math.random() * 8)
}
var position
while (-1) {
position = this.getPosition(ant.x, ant.y, ant.vector)
if (this.hitBox(position.x, position.y)) {
ant.vector = Math.floor(Math.random() * 8)
continue
}
break
}
if (this.hitAnt(position.x, position.y))
return
ant.x = position.x
ant.y = position.y
},
hitBox(x, y) {
return x < 0 || x >= 20 || y < 0 || y >= 20
},
hitAnt(x, y) {
for (let ant of this.ants) {
if (x == ant.x && y == ant.y)
return true
}
return false
},
isEatingCandy(ant) {
for (let candy of this.candies) {
if (candy.x == ant.x && candy.y == ant.y) {
return true
}
}
return false
},
getNearbyCandy(ant) {
for (let candy of this.candies) {
if (candy.x - 1 <= ant.x && ant.x <= candy.x + 1
&& candy.y - 1 <= ant.y && ant.y <= candy.y + 1) {
return candy
}
}
return null
},
isEmpty(x, y) {
for (let ant of this.ants) {
if (x == ant.x && y == ant.y)
return false
}
return true
},
getPosition(x, y, vector) {
switch (vector) {
case 0: return { x: x - 1, y: y + 1 }
case 1: return { x: x - 0, y: y + 1 }
case 2: return { x: x + 1, y: y + 1 }
case 3: return { x: x - 1, y: y + 0 }
case 4: return { x: x - 1, y: y - 1 }
case 5: return { x: x - 0, y: y - 1 }
case 6: return { x: x - 1, y: y - 1 }
case 7: return { x: x - 1, y: y + 0 }
}
},
proceed() {
for (let ant of this.ants) {
this.calculateAntsBehavior(ant)
}
},
}
})
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
body {
background-color: white;
cursor: default;
box-sizing: border-box;
}
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
html {
font-family: sans-serif;
line-height: 1.15;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
article,
aside,
footer,
header,
nav,
section {
display: block;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
figcaption,
figure,
main {
display: block;
}
figure {
margin: 1em 40px;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
pre {
font-family: monospace, monospace;
font-size: 1em;
}
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active,
a:hover {
outline-width: 0;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: inherit;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
dfn {
font-style: italic;
}
mark {
background-color: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
audio,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
img {
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html [type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
progress {
display: inline-block;
vertical-align: baseline;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
details,
menu {
display: block;
}
summary {
display: list-item;
}
canvas {
display: inline-block;
}
template {
display: none;
}
[hidden] {
display: none;
}
input:focus,
input.__focus {
outline: 4px solid rgba(117, 170, 255, 0.5);
}
button:focus,
button.__focus {
outline: 4px solid rgba(117, 170, 255, 0.5);
}
button:active,
button.__active {
-ms-transform: scale(0.97);
transform: scale(0.97);
}
::-moz-selection {
background-color: #75aaff;
}
::selection {
background-color: #75aaff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment