In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)05/31 Report--
Today, the editor will share with you how Vue+TailWindcss can achieve a simple breakthrough on Mini Game, with detailed content and clear logic. I believe most people still know too much about this knowledge, so share this article for your reference. I hope you can get something after reading this article. Let's take a look at it.
Introduction to the game
This is a 2d puzzle game, players have to avoid enemies and traps to reach the finish line with multiple levels
You can customize the level and retain the data.
Realization technology
Vue tailwindcss
The characteristics of this tour
Custom checkpoint
The enemy automatically seeks the enemy.
Low technical ability
You win!
Technical implementation initialization page
Create a json file to hold the variables of the initial level (only one level. ) set the size of the square, the initialization variable speed is set to 176.The width and height of the chessboard is 4 speed, the width and height of the square is 1 speed, the square moves one grid is speed * 1, and two squares is speed * 2
Const speed = ref
Level is a json file containing the variables of the first level, which are used to initialize a level when there is no level.
Level.json
[{"id": 1 enemy_top / first level "speed": 176 id pinch / square size "top": 528 Zhe / protagonist left value "left": 0 minute pinch / protagonist enemy_top_2 value "enemy_top": 0 penny pinch / enemy top value "enemy_left": 352 Gramps / enemy Left value "enemy_top_2": 528 / / enemy_left_2 value of Enemy 2 "enemy_left_2": 352 enemy_left_2 value of Enemy 2 "trap_left": 176 Grampash / obstacle value "obstacle_left": 352 pound / obstacle value "trap_top": 352 pound / Trap value "trap_left": 176 Gramps / Trap value "spot_top": 0 / / end top value "spot_left": 528max / end Left value}]
Determine if there is any data when loading the page. If not, add it.
Import Level from ".. / api/level.json"; let res = JSON.parse (localStorage.getItem ("data")); if (! res) {localStorage.setItem ("data", JSON.stringify (Level));} Square Settings
Use absolute positioning and use transition-all to make the square look animated
Set specific top and left for the cube, declare the variable and then set it to the cube
Const Level = JSON.parse (localStorage.getItem ("data")); const spot_top = ref (level [index] .spot _ top); const spot_left = ref (level [index] .spot _ left); const enemy_top = ref (level [index] .spot _ top); const enemy_left = ref (level [index] .spot _ left); the protagonist moves
Execute the corresponding function when the corresponding key is pressed
Document.addEventListener ("keydown", (e) = > {switch (e.key) {case "a": if (is_run.value) {moveProtagonistA ();} break; case "w": if (is_run.value) {moveProtagonistW ();} break; case "d": if (is_run.value) {moveProtagonistD ()) } break; case "s": if (is_run.value) {moveProtagonistS ();} break; case "r": againGame (); / / restart break;}})
The four functions mean the movement of the protagonist block up and down, left and right, in essence, but the difference is that each top and left are different, so let's choose one to explain it in detail:
When you want the main character to move to the left
Const moveProtagonistA = () = > {/ / suicide judgment if (left.value = = enemy_left.value + speed.value & & top.value = = enemy_top.value) {left.value-= speed.value; return false;} if (left.value = = 0) {/ / Boundary judgment left.value =-20; setTimeout () = > {left.value = 0;}, 100); return false } / / obstacle judgment obstacle = obstacle_left.value + speed.value; if (top.value = = obstacle_top.value & & left.value = = obstacle) {left.value = obstacle-20; setTimeout () = > {left.value = obstacle;}, 100);} else {left.value-= speed.value; freeFindEnemy (enemy_top, enemy_left); freeFindEnemy (enemy_top_2, enemy_left_2);}}
The content of the function as a whole is a little smaller, let's explain it separately:
Suicide judgment
Because when the protagonist moves, the enemy's automatic enemy hunting function will also be turned on, so when the protagonist moves to the enemy, it will be staggered with the protagonist because the enemy automatically seeks the enemy, so this logic is born, that is, to judge that if the protagonist's next step is an enemy, the enemy will stay where he is and install the enemy game over.
/ / suicide judgment if (left.value = = enemy_left.value + speed.value & & top.value = = enemy_top.value) {left.value-= speed.value; return false;// if suicide succeeds, stop the following enemy judgment}
Boundary judgment
If it goes out of bounds, it will be intercepted and give a hint of the blocked effect, because this example is when you want to move to the left, so the judgment condition is also on the left.
If (left.value = = 0) {/ / this effect can make the square rebound left.value =-20; setTimeout (() = > {left.value = 0;}, 100); if return false;// encounters the boundary, it will prevent the judgment of the enemy like the one below.
Obstacle judgment & to seek out the enemy
If there is an obstacle in the level, when the protagonist touches the obstacle, it will have the same rebound effect as the boundary judgment to indicate that the road is blocked.
If the movement of the protagonist does not encounter obstacles, then execute the command of normal movement and automatically seek the enemy.
Obstacle = obstacle_left.value + speed.value;if (top.value = = obstacle_top.value & & left.value = = obstacle) {/ / as above, rebound left.value = obstacle-20; setTimeout (() = > {left.value = obstacle;}, 100);} else {left.value-= speed.value;// mobile command freeFindEnemy (enemy_top, enemy_left) / / freeFindEnemy (enemy_top_2, enemy_left_2) of enemy 1; / / the enemy of enemy 2}
As you may have seen (Dora waving her hand), the last two functions used in the enemy, this function is the logic of the automatic enemy, and then go further.
Automatically seek the enemy
When the protagonist moves, the enemy automatically seeks the enemy.
/ / automatic enemy const freeFindEnemy = (Etop: any, Eleft: any) = > {let _ top = top.value-Etop.value; let _ left = left.value-Eleft.value; if (Math.abs (_ top) > Math.abs (_ left)) {if (_ top > 0) {moveEnemyS (Etop, Eleft);} else {moveEnemyW (Etop, Eleft);} else {if (_ left > 0) {moveEnemyD (Etop, Eleft) } else {moveEnemyA (Etop, Eleft);}
The function moveEnemy series appears in this is the direction of the enemy box. The logic is to judge the protagonist's distance from the enemy's top and left to determine the direction of the enemy's box. Etop and Eleft need to pass in the enemy's top and Left values respectively, and judge which way to move when the distance is large. There are two cases: greater than or less than or equal to.
It is extended by automatically soliciting the enemy-- the enemy moves.
The enemy is moving
The enemy movement also has four functions, which is basically no different from the protagonist's movement, but the enemy will choose to bypass when it encounters obstacles, and the enemy will be "eaten" when it encounters a trap.
Take the enemy's downward movement as an example.
Const moveEnemyS = (Etop: any, Eleft: any) > {/ / Trap judgment if (trap_top.value = = Etop.value & & trap_left.value = = Eleft.value) return; / / obstacle detection judgment obstacle = obstacle_top.value-speed.value; if (Etop.value = = obstacle & & Eleft.value = = obstacle_left.value) {/ / judge if you encounter obstacles let _ left = left.value-Eleft.value If (_ left > 0) {Eleft.value + = speed.value;} else {Eleft.value-= speed.value;}} else {Etop.value + = speed.value;}}
The first is the judgment of the trap. If the enemy's top and left are consistent with the trap, it is judged that the enemy has fallen into the trap, which will terminate all enemy movements.
Next is the obstacle. Judge that if there is an obstacle in the direction the enemy is about to go, judge the distance from the protagonist to avoid it to the left or right.
Victory and defeat
All actions must be terminated after victory and defeat, and all actions are also triggered by the mobile function of the protagonist, so first declare a variable to control the progress of the game, and then judge the variable by pressing the keystroke. If the game is in progress, the mobile function is triggered, and if the game has not started or failed, the trigger event is skipped, that is, there is no response.
Case "a": / / is_run is the declared variable, which is false if (is_run.value) {moveProtagonistA ();} break in the failed or unstarted phase of the game.
When the victory conditions are met (that is, the protagonist hits the finish line), win is triggered, that is, the word win is displayed and is_run is set to false
/ / whether the topleft of the protagonist coincides with the topleft of the destination if (top.value = = spot_top.value & & left.value = = spot_left.value) {winShow.value = true; is_run.value = false;}
When the failure condition is met (that is, the protagonist encounters enemy 1 or 2 or a trap), lose is triggered, which displays the word lose and sets is_run to false
If ((top.value = = enemy_top.value & & left.value = = enemy_left.value) | | (top.value = = enemy_top_2.value & & left.value = = enemy_left_2.value) | (top.value = = trap_top.value & & left.value = = trap_left.value)) {is_run.value = false; loseShow.value = true; return;}
The function of the last return is to truncate, and when the lose is triggered, the execution will not continue (otherwise the win will be executed)
Edit the level to move in and out to change color
16 black blocks to judge the color by moving the mouse in and out
Const editMove = (event, item) = > {/ / if the box has been selected, do nothing if (! item.is_confirm) {for (let i in blockList.value) {/ / select the corresponding square to change color if (blockList.value [I] .id = = item.id) {blockList.value.background = "" } else if (blockList.value.is _ confirm) {blockList.value.background = "";} else {blockList.value.background = "# 000";} Const editLeave = () = > {for (let i in blockList.value) {/ / if the box has been selected, do nothing if (blockList.value.is _ confirm) {blockList.value.background = ";} else {/ / select the corresponding square to change color blockList.value.background =" # 000 ";}
Because the color of the square cannot be changed after it is set, these two methods are needed to judge the square that has been set.
Click Settings
First click on the left legend to select the color, and then click the box to change color.
Legend
{{item.introduce}} const legendList = [{id: 0, color: "bg-green-500", introduce: "destination",}, {id: 1, color: "bg-red-500", introduce: "enemy",}, {id: 2, color: "bg-blue-500", introduce: "protagonist",}, {id: 3 Color: "bg-gray-500", introduce: "obstacles",}, {id: 4, color: "bg-purple-500", introduce: "traps",},]
Discoloration logic
Const editMove = (event, item) = > {if (! item.is_confirm) {for (let i in blockList.value) {if (blockList.value.id = = item.id) {/ / focus on these two sentences blockList.value.background = ""; blockList.value.color = color.value } else if (blockList.value.is _ confirm) {blockList.value.background = "";} else {blockList.value.background = "# 000";} Const editClick = (event, item) = > {/ / json add switch (color.value) {case "bg-green-500": if (json.spot_top! = 9999) {tips.value = "only one end point"; return;} json.spot_top = item.top; json.spot_left = item.left; break Case "bg-red-500": if (json.enemy_top! = 9999) {if (json.enemy_top_2! = 9999) {tips.value = "only two enemies"; return;} json.enemy_top_2 = item.top; json.enemy_left_2 = item.left; break;} json.enemy_top = item.top Json.enemy_left = item.left; break; case "bg-blue-500": if (json.top! = 9999) {tips.value = "only one protagonist"; return;} json.top = item.top; json.left = item.left; break Case "bg-gray-500": if (json.obstacle_top! = 9999) {tips.value = "only one obstacle"; return;} json.obstacle_top = item.top; json.obstacle_left = item.left; break; case "bg-purple-500": if (json.trap_top! = 9999) {tips.value = "only one trap" Return;} json.trap_top = item.top; json.trap_left = item.left; break; default: tips.value = "Please select color ~"; return;} / / status retention for (let i in blockList.value) {if (blockList.value [I] .id = = item.id) {blockList.value.background = "" Is _ confirm = true;} else if (blockList.value [I] .is _ confirm) {blockList.value [I] .background = ";} else {blockList.value.background =" # 000 ";}
First of all, the color is saved by clicking the legend, and then when the mouse is moved into the black block, it is no longer white, but the selected color, which can be fixed to the black block when clicked.
Because style has a higher priority than class (background is higher than bg-red-500), you need to remove the background color when hovering:
BlockList.value.background = ""; blockList.value.color = color.value
You need to keep this color when you click, so change the original color when you click, and it won't change color after floating.
BlockList.value [I] .background = ""; blockList.value.color = color.value; blockList.value [I] .is _ confirm = true
Is_confirm has appeared above once or twice, indicating whether the block is set or not, and if it is set, no action is done on it.
Const editMove = (event, item) = > {if (! item.is_confirm) {...}}; save the level
Remember the location of each set block and put it in the local storage when you click the save level, so that a new level is generated.
[gif save level]
Initially, set all top left to 9999. Record the top left and color of the box when you click the box to pass data into an array, and limit the number of blocks. Here, take the protagonist as an example:
Switch (color.value) {case "bg-blue-500": if (json.top! = 9999) {tips.value = "only one protagonist"; return;} / / fill in the top lef of the protagonist in the corresponding place json.top = item.top; json.left = item.left; break;}
Add an array to the local storage when you click Save level
Const Level = JSON.parse (localStorage.getItem ("data")); let json = {id: Level.length + 1, speed: 176, top: 9999, left: 9999, enemy_top: 9999, enemy_left: 9999, enemy_top_2: 9999, enemy_left_2: 9999, obstacle_top: 9999, obstacle_left: 9999, trap_top: 9999, trap_left: 9999, spot_top: 9999, spot_left: 9999,} .. const saveClick = () = > {Level.push (json); localStorage.setItem ("data", JSON.stringify (Level)); button_text.value = "saved successfully"; router.push ("/ main");}. That's all of the article "how to achieve a simple break through Mini Game with Vue+TailWindcss". Thank you for reading! I believe you will gain a lot after reading this article. The editor will update different knowledge for you every day. If you want to learn more knowledge, please pay attention to the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.