tag:crieit.net,2005:https://crieit.net/tags/%E3%82%A8%E3%82%A4%E3%83%97%E3%83%AA%E3%83%AB%E3%83%95%E3%83%BC%E3%83%AB/feed
「エイプリルフール」の記事 - Crieit
Crieitでタグ「エイプリルフール」に投稿された最近の記事
2019-04-01T11:02:55+09:00
https://crieit.net/tags/%E3%82%A8%E3%82%A4%E3%83%97%E3%83%AA%E3%83%AB%E3%83%95%E3%83%BC%E3%83%AB/feed
tag:crieit.net,2005:PublicArticle/14896
2019-04-01T07:14:06+09:00
2019-04-01T11:02:55+09:00
https://crieit.net/posts/c4e13ccbb7ff6ffbec992d58cf06261c
エイプリルフールはじめました
<p>リリースしてからはじめてのエイプリールフールだったのでちょっと遊んでみました。ふわふわと飛んでいるのはくりえいとくんです。</p>
<p><a href="https://crieit.now.sh/upload_images/cf9086966f7925dc9e21645fb9bf8e125ca0d778569a6.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cf9086966f7925dc9e21645fb9bf8e125ca0d778569a6.png?mw=700" alt="" /></a></p>
<p>元々</p>
<p>Crieit</p>
<p>という文字が顔に見えたのでそれをそのまま絵にしてみたらおばけになった、という感じです。クリックすると色々喋ります。</p>
<p><img src="/img/aprilfool/crieit.png" alt="" /></p>
<p>特筆することも無いので動き回らせているプログラムでも貼っておきます。</p>
<h2 id="おばけクラス"><a href="#%E3%81%8A%E3%81%B0%E3%81%91%E3%82%AF%E3%83%A9%E3%82%B9">おばけクラス</a></h2>
<p><code>move()</code>で動かし、<code>getX()</code>と<code>getY()</code>で表示するための位置を取得しているだけのよくあるクラスです。</p>
<p>Goast.ts</p>
<pre><code class="javascript">const ymax = 50
const width = 100
export default class Ghost {
id: number
private x = 0
private y = 0
private basey = 0
private ax = 0
private angle = 0
constructor() {
this.id = Date.now()
if (Math.round(Math.random()) === 0) {
this.x = -width
this.ax = Math.floor(Math.random() * 2 + 2)
} else {
this.x = window.innerWidth
this.ax = -Math.floor(Math.random() * 2 + 2)
}
this.basey = Math.floor(Math.random() * window.innerHeight)
this.calculateY()
}
calculateY() {
this.y = this.basey + Math.sin(this.angle) * ymax
}
move() {
this.x += this.ax
this.angle += Math.PI / 50
if (this.angle >= Math.PI * 2) {
this.angle -= Math.PI * 2
}
this.calculateY()
}
finished() {
if (this.ax < 0 && this.x < -width) {
return true
}
if (this.ax > 0 && this.x > window.innerWidth) {
return true
}
return false
}
getX() {
return this.x
}
getY() {
return Math.floor(this.y)
}
getAx() {
return this.ax
}
}
</code></pre>
<h2 id="おばけたちの管理コンポーネント"><a href="#%E3%81%8A%E3%81%B0%E3%81%91%E3%81%9F%E3%81%A1%E3%81%AE%E7%AE%A1%E7%90%86%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88">おばけたちの管理コンポーネント</a></h2>
<p>これも特に特筆することのない単なるゲームループ的なコンポーネントです。おばけを管理して画面からはみ出したら削除したりしています。</p>
<pre><code class="html"><template>
<div>
<AprilfoolGhost v-for="ghost in ghosts" :key="ghost.id" :ghost="ghost"></AprilfoolGhost>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import Aprilfool from './Aprilfool.vue'
import AprilfoolGhost from './AprilfoolGhost.vue'
import Ghost from './Ghost'
@Component({
components: { AprilfoolGhost }
})
export default class AprilfoolGhosts extends Aprilfool {
ghosts: Ghost[] = []
mounted() {
if (!this.isAprilfool()) {
return
}
setInterval(() => {
if (this.ghosts.length < 10) {
this.ghosts.push(new Ghost())
}
}, 5000)
setInterval(() => {
this.moveAll()
}, 41)
}
moveAll() {
const ghosts: Ghost[] = []
this.ghosts.forEach((ghost, index) => {
ghost.move()
if (!ghost.finished()) {
ghosts.push(ghost)
}
})
this.ghosts = ghosts
}
}
</script>
</code></pre>
<h2 id="おばけコンポーネント"><a href="#%E3%81%8A%E3%81%B0%E3%81%91%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88">おばけコンポーネント</a></h2>
<p>もう動きはおばけクラス、管理は前述のコンポーネントで行われているので、ここでは表示したりクリックイベントを処理したりするだけです。これで一通り完了です。面倒だったので表示はfixedにしてスクロールは考慮しないようにしています。</p>
<pre><code class="html"><template>
<div>
<a @click.prevent="showMessage()" :style="getStyle()">
<img src="/img/aprilfool/crieit.png" :class="getClass()">
</a>
<div :style="getFukidashiStyle()" class="fukidashi">
<div class="d-flex justify-content-center align-items-center">
<div v-html="message"></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
import Ghost from './Ghost'
const messages = [
'Happy Halloween!',
'Trick or Treat??',
:
:
]
@Component
export default class AprilfoolGhost extends Vue {
@Prop(Object) ghost: Ghost
isMessageShown = false
message = ''
getStyle() {
return {
left: `${this.ghost.getX()}px`,
top: `${this.ghost.getY()}px`
}
}
getClass() {
return {
reverse: this.ghost.getAx() < 0
}
}
getFukidashiStyle() {
return {
left: this.ghost.getX() - 200 + 'px',
top: this.ghost.getY() - 200 + 'px',
opacity: this.isMessageShown ? 1 : 0
}
}
showMessage() {
if (this.isMessageShown) {
return
}
this.message = messages[Math.floor(Math.random() * messages.length)]
this.isMessageShown = true
setTimeout(() => {
this.isMessageShown = false
}, 5000)
}
}
</script>
<style scoped>
div > * {
display: block;
position: fixed;
opacity: 0.8;
}
.reverse {
transform: scale(-1, 1);
}
.fukidashi {
background: url(/img/aprilfool/fukidashi.png);
width: 274px;
height: 200px;
opacity: 0;
transition-duration: 0.2s;
}
.fukidashi > div {
margin-left: 40px;
margin-top: 20px;
width: 200px;
height: 100px;
font-size: 1.8rem;
}
</style>
</code></pre>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>さあ、みなさんも新元号のことは忘れてエイプリールフールやりましょう。今からでも間に合います!!!!!(?)</p>
だら@Crieit開発者