“This is the third day of my participation in the First Challenge 2022. For details: First Challenge 2022”
I’ll put the 0 out front
Red envelopes, also known as lucky money, are gifts of money wrapped in red paper given to children during the Lunar New Year. It is said that during the Ming and Qing dynasties, lucky money was mostly given to children with red strings. After the Republic of China, it evolved to be wrapped in red paper. Traditional Chinese red envelope culture in the folk, communities, companies also follow such rites. Apart from the Spring Festival, it is also customary to give red envelopes on other happy occasions, such as weddings and new store openings.
In this issue, we created a red envelope rain game with code, as shown below. After reading this article, I believe you can also complete such a small game design.
1 Preparations
Build the project using Vue. The process for
- vue init webpack vue-demo
- cd vue-demo
- cnpm install # npm install
Download some festive pictures from the Internet as the background and red envelope style, these styles can be selected, to the students who want to live fully enough freedom.
Design HTML+CSS styles
The HTML style is very simple, mainly divided into two parts: red envelope rain and grab red envelope panel.
<! -- Rain of red envelopes -->
<div id="wrapper"></div>
<! -- Grab red envelope panel -->
<div id="panel">
<div id="hb">
<span id="text">{{ result }}</span>
<div id="btn" @click="gameOn">Continue to grab red envelopes</div>
</div>
</div>
Copy the code
CSS styles are slightly more complex and are presented in the complete code below. One of the least used is the Annimation animation rendering style
animation: dropDowm 3s forwards; /* Rotate animation */
@keyframes dropDowm {
0% {
top: 0px;
transform: translateY(-100%) rotate(0deg);
}
100% {
top: 110%;
transform: translateY(0%) rotate(360deg); }}Copy the code
Here, the common parameters of Annimation are as follows:
- Animation-name: indicates the animation name of the keyframe
- Animation-duration: animation execution time
- Animation-timing -function: animation speed function
- Animation-delay: indicates the animation delay time
- Animation-rotund-count: number of animation executions
- Animation-direction: indicates the animation execution direction
alternate
(Interval movement),reverse
(Reverse motion),reverse-alternate
(Reverse interval motion) - Animation-fill-mode: Specifies the style to be applied to an element when the animation does not play (when the animation is complete, or when the animation has a delay before it starts playing), containing
forwards
(Animation stops at the position of last keyframe),backwards
(the first key frame of the animation executes immediately),both
(The first keyframe also stops at the last keyframe)
After the design is completed, the running results are shown in the figure below, which are background and panel respectively.
Design JavaScript logic
The logic of the program is shown below
Graph TD A[start] --> B B --> C{ } C - - - > D (display the amount of the grab) C - n - > E (continue) D - > F {red envelopes to set number? } E -->F{Does the number of red packets reach the set value? } F -- yes --> G(display game results) F -- no --> B
The most critical thing above is to monitor the user’s behavior of grabbing red envelopes and judge whether they have grabbed red envelopes. The design of the monitoring function is as follows. If the red envelopes are successfully grabbed, the total amount will be automatically accumulated.
mouseHandler(e) {
var event = e || window.event,
money = event.target.dataset.money;
if (money) {
this.result = "Congratulations on getting the red envelope." + money + "Yuan";
for (var i = 0, len = this.imgList.length; i < len; i++) {
this.imgList[i].style.animationPlayState = "paused";
}
panel.style.display = "block";
this.totalMoney += Number(money); }}Copy the code
Next, we need to consider how to let the red envelope randomly drop, the core code is as follows:
for (var i = 0; i < num; i++) {
let img = new Image();
img.src = this.imgUrl;
// Randomly set the distribution of red packets
img.style.left = this.ranNum(0.window.innerWidth) + "px";
let delay = this.ranNum(0.100) / 10;
// Set the red envelope time
img.style.animationDelay = delay + "s";
if (this.delayTime < delay) {
this.delayTime = delay;
this.lastImg = img;
}
// Set the amount of each red envelope
img.dataset.money = this.ranNum(0.1000) / 100;
Copy the code
The other functions basically serve these two core functions, so I won’t go into details here.
4 Complete Code
<template>
<div id="app">
<! -- Rain of red envelopes -->
<div id="wrapper"></div>
<! -- Grab red envelope panel -->
<div id="panel">
<div id="hb">
<span id="text">{{ result }}</span>
<div id="btn" @click="gameOn">Continue to grab red envelopes</div>
</div>
</div>
</div>
</template>
Copy the code
<script>
export default {
name: "App".data() {
return {
totalMoney: 0.// The total amount of the red packets
delayTime: 0./ / delay
lastImg: null.// The last dropped image
imgList: null.// A random sequence of red packets
result: "".// Game results
imgUrl: require("./assets/hongbao.jpg"),}; },methods: {
// @breif: Start the game
start() {
let dom = this.createDom(20);
this.imgList = document.getElementsByTagName("img");
document.getElementById("wrapper").appendChild(dom);
},
// @breif: Create a red envelope sequence
createDom(num) {
// Create a document fragment
let frag = document.createDocumentFragment();
for (var i = 0; i < num; i++) {
let img = new Image();
img.src = this.imgUrl;
// Randomly set the distribution of red packets
img.style.left = this.ranNum(0.window.innerWidth) + "px";
let delay = this.ranNum(0.100) / 10;
// Set the red envelope time
img.style.animationDelay = delay + "s";
if (this.delayTime < delay) {
this.delayTime = delay;
this.lastImg = img;
}
// Set the amount of each red envelope
img.dataset.money = this.ranNum(0.1000) / 100;
frag.appendChild(img);
}
return frag;
},
// @breif: Keep playing
gameOn() {
document.getElementById("panel").style.display = "none";
for (let i = 0, len = this.imgList.length; i < len; i++) {
this.imgList[i].style.animationPlayState = "running"; }},// Listen for mouse events
mouseHandler(e) {
var event = e || window.event,
money = event.target.dataset.money;
if (money) {
this.result = "Congratulations on getting the red envelope." + money + "Yuan";
for (var i = 0, len = this.imgList.length; i < len; i++) {
this.imgList[i].style.animationPlayState = "paused";
}
panel.style.display = "block";
this.totalMoney += Number(money); }},// Listen for animation events
annimationHandler(e) {
document.getElementById("panel").style.display = "block";
this.result = "Congratulations on the total." + this.totalMoney.toFixed(2) + "Yuan";
},
// @breif: generates random numbers between min and Max
ranNum(min, max) {
return Math.ceil(Math.random() * (max - min) + min); }},mounted() {
this.start();
window.addEventListener("mousedown".this.mouseHandler);
this.lastImg.addEventListener("webkitAnimationEnd".this.annimationHandler); }}; </script>Copy the code
<style>
* {
padding: 0;
margin: 0;
}
body {
height: 100%;
width: 100%;
background: url("./assets/background.jpg");
background-size: cover;
overflow: hidden;
}
#wrapper img {
position: absolute;
transform: translateY(-100%); /* Drop animation */
animation: dropDowm 3s forwards; /* Rotate animation */
}
@keyframes dropDowm {
0% {
top: 0px;
transform: translateY(-100%) rotate(0deg);
}
100% {
top: 110%;
transform: translateY(0%) rotate(360deg); }}#panel {
display: none;
}
#panel::before {
content: "";
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0.0.0.0.5);
}
#hb {
width: 350px;
height: 450px;
border-radius: 20px;
background-color: #e7223e;
color: #fad755;
position: fixed;
left: 50%;
top: 50%;
margin-top: -225px;
margin-left: -175px;
font-size: 30px;
font-weight: 900;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#btn {
background-color: #fad755;
color: #e7223e;
font-size: 18px;
margin-top: 10px;
padding: 10px;
border: none;
outline: none;
cursor: pointer;
}
</style>
Copy the code