js+svg实现Wordscapes拼单词拼字游戏代码

代码语言:html

所属分类:游戏

代码描述:js+svg实现Wordscapes拼单词拼字游戏代码,按住鼠标左键不放将字母连成一个单词。

代码标签: js svg Wordscapes 拼单词 拼字 游戏 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  

  <meta name="viewport" content="width=device-width, initial-scale=1">
  
  
  
<style>
/* ["#5CEEAD","#8FDDE0","#C2AAEB","#F577B8","#D64485"] */
body {
	background: #8fdde0;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cpattern id='p' width='250' height='30' viewBox='0 0 1000 120' patternUnits='userSpaceOnUse'%3E%3Cg fill='none' stroke='%235CEEAD' stroke-width='10'%3E%3Cpath d='M-500 75c0 0 125-30 250-30S0 75 0 75s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.6' /%3E%3Cpath d='M-500 45c0 0 125-30 250-30S0 45 0 45s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.4' /%3E%3Cpath d='M-500 105c0 0 125-30 250-30S0 105 0 105s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.3' /%3E%3Cpath d='M-500 15c0 0 125-30 250-30S0 15 0 15s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.3' /%3E%3Cpath d='M-500-15c0 0 125-30 250-30S0-15 0-15s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.4' /%3E%3Cpath d='M-500 135c0 0 125-30 250-30S0 135 0 135s125 30 250 30s250-30 250-30s125-30 250-30s250 30 250 30s125 30 250 30s250-30 250-30' opacity='0.6' /%3E%3C/g%3E%3C/pattern%3E%3Crect height='100%25' width='100%25' fill='url(%23p)' /%3E%3C/svg%3E");
	margin: 0 auto;
	height: 100vh;
	width: 100vw;
}
#wordscapesGame {
	position: absolute;
	bottom: 40px;
	left: 50%;
	transform: translate(-50%);
	height: 400px;
	width: 400px;
	max-height: 100vh;
	max-width: 100vw;
	z-index: 10;
}
#wordscapesGame text {
	font-family: "Roboto", sans-serif;
}
.blurry {
	position: absolute;
	height: 15px;
	width: 100px;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	border-radius: 5px;
	backdrop-filter: blur(6px);
	-moz-backdrop-filter: blur(6px); /* For Safari */
	-webkit-backdrop-filter: blur(6px); /* For Safari */
/* 	background-color: #C2AAEB; */
	transition: height 200ms;
}
.reveal:focus > .blurry, .reveal:active > .blurry {
	height: 0px;
}
.strike {
	text-decoration: line-through;
}
.letter:hover > circle {
	fill: #f577b8;
}

.letterText {
	user-select: none;
	pointer-events: none;
	-webkit-transition: transform 400ms; /* Safari */
	-moz-transition: transform 400ms; /* Safari */
	transition: transform 400ms;
}
.letterCircle {
	-webkit-transition: transform 400ms; /* Safari */
	-moz-transition: transform 400ms; /* Safari */
	transition: transform 400ms;
}

.letter {
	-webkit-transition: transform 400ms; /* Safari */
	-moz-transition: transform 400ms; /* Safari */
	transition: transform 400ms;
	cursor: pointer;
}
.shuffle, .awards {
	cursor: pointer;
	background: none;
	color: #fff;
	padding: 10px;
	height: 65px;
	width: 65px;
	position: absolute;
	top: 50%;
	left: 20px;
	transform:translate(0, -50%);
	border: 2px solid rgba(255, 255, 255, 0.3);
	border-radius: 50%;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
}
.awards {
	top: 20px;
	transform: none;
}
.shuffle:hover {
	border: 2px solid #fff;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
}

.coinDestination {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
	height: 55%;
	width: 55%;
}
.circleBG {
	user-select: none;
	pointer-events: none;
	fill: #c2aaeb;
}
.selected {
	fill: #f577b8;
	stroke: #d64485;
}
.circleShadow {
	-webkit-transition: r 500ms; /* Safari */
	transition: r 500ms;
}
.circleBG {
	-webkit-transition: r 200ms; /* Safari */
	transition: r 200ms;
}
.connector,
.connectedLetters {
	stroke: #d64485;
}
.currentWord {
	position: absolute;
	bottom: 10px;
	left: 50%;
	transform: translate(-50%);
	font-family: "Roboto", sans-serif;
	color: rgba(0, 0, 0, 0.5);
	font-size: 1.5em;
}

.noTouch {
	user-select: none;
	pointer-events: none;
}

/* MENU STUFF */
#menuCheck, #menuCheckL {
	--menuBG: #c2aaeb;
	--menuW: 200px;
}
.menu > .menuInner {
	height: calc(100% - 75px);
	padding-bottom: 25px;
	padding-top: 25px;
	overflow-y: auto;
	font-family: "Roboto", sans-serif;
}
.menuInner .menuInstructions {
	margin-bottom: 10px;
	margin-left: 10px;
	padding: 10px;
	text-align: center;
}
.menuInner button {
	background: rgba(0, 0, 0, 0.4);
	border: none;
	border-radius: 5px;
	color: #fff;
	cursor: pointer;
	margin-bottom: 10px;
	margin-left: 10px;
	padding: 10px;
	position: relative;
	width: calc(var(--menuW) - 30px);
}
.menuInner button:hover {
	box-shadow: inset 0px 0px 2px 1px #fff;
}
.menuInner::-webkit-scrollbar-thumb {
	background: rgba(255, 255, 255, 0.5);
	border-radius: 10px;
}
.menuInner::-webkit-scrollbar-thumb:hover {
	background: rgba(255, 255, 255, 0.7);
}
.menuInner::-webkit-scrollbar {
	width: 6px;
}
.menuInner::-webkit-scrollbar-track {
	box-shadow: inset 0 0 3px #ccc;
	border-radius: 10px;
}
#menuCheck .menu {
	background: var(--menuBG);
	display: block;
	height: 100%;
	position: fixed;
	right: calc(var(--menuW) * -1);
	top: 0px;
	-webkit-transition: 300ms; /* Safari */
	transition: 300ms;
	width: var(--menuW);
	z-index: 99;
}
#menuCheck #menuCheckBox {
	display: none;
}
#menuCheck label {
	background-color: rgba(194, 170, 235, 0.2);
	border: 2px solid rgba(255, 255, 255, 0.25);
	border-radius: 50%;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	color: #fff;
	font-family: "Roboto", sans-serif;
	cursor: pointer;
	height: 65px;
	position: fixed;
	right: 20px;
	top: 20px;
	-webkit-transition: right 300ms; /* Safari */
	transition: right 300ms;
	user-select: none;
	width: 65px;
	z-index: 100;
	text-align: center;
}
#menuCheck label:hover {
	border: 2px solid rgba(255, 255, 255, 1);
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
}
#menuCheck #menuCheckBox:checked + label {
	content: "0";
	box-shadow: -1px 2px 5px #000;
	right: calc(var(--menuW) + 5px);
}
#menuCheck label:before {
	content: "";
	display: block;
	height: 100%;
	position: absolute;
	right: 0px;
	width: 100px;
}
#menuCheck #menuCheckBox:checked + #menuCheck label {
	right: var(--menuW);
}
#menuCheck #menuCheckBox:checked + label:before {
	height: 100vh;
	transform: translate(0, -20px);
	width: calc(100vw - var(--menuW));
}
#menuCheck #menuCheckBox:checked ~ .menu {
	box-shadow: -2px 0px 5px #000;
	right: 0%;
}

#menuCheckL .menu {
	background: var(--menuBG);
	display: block;
	height: 100%;
	position: fixed;
	left: calc(var(--menuW) * -1);
	top: 0px;
	-webkit-transition: 300ms; /* Safari */
	transition: 300ms;
	width: var(--menuW);
	z-index: 99;
}
#menuCheckL #menuCheckBoxL {
	display: none;
}
#menuCheckL label {
	background-color: rgba(194, 170, 235, 0.2);
	border: 2px solid rgba(255, 255, 255, 0.25);
	border-radius: 50%;
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
	color: #fff;
	font-family: "Roboto", sans-serif;
	cursor: pointer;
	height: 65px;
	position: fixed;
	left: 20px;
	top: 20px;
	-webkit-transition: left 300ms; /* Safari */
	transition: left 300ms;
	user-select: none;
	width: 65px;
	z-index: 100;
	text-align: center;
}
#menuCheckL label:hover {
	border: 2px solid rgba(255, 255, 255, 1);
	box-sizing: border-box;
	-moz-box-sizing: border-box;
	-webkit-box-sizing: border-box;
}
#menuCheckL #menuCheckBoxL:checked + label {
	content: "0";
	box-shadow: -1px 2px 5px #000;
	left: calc(var(--menuW) + 5px);
}
#menuCheckL label:before {
	content: "";
	display: block;
	height: 100%;
	position: absolute;
	left: 0px;
	width: 100px;
}
#menuCheckL #menuCheckBoxL:checked + #menuCheckL label {
	left: var(--menuW);
}
#menuCheckL #menuCheckBoxL:checked + label:before {
	height: 100vh;
	transform: translate(0, 20px);
	width: calc(100vw - var(--menuW));
}
#menuCheckL #menuCheckBoxL:checked ~ .menu {
	box-shadow: 2px 0px 5px #000;
	left: 0%;
}

.wordsComplete {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
}
.header {
	text-align: center;
	padding: 5px;
	font-family: "Roboto", sans-serif;
	color: #fff;
}
.newGame {
	position: absolute;
	bottom: 10px;
	left: 10px;
	padding: 5px;
	border: 2px solid rgba(255,255,255,0.5);
	background: none;
	color: #fff;
	border-radius: 5px;
	cursor: pointer;
}
.newGame:hover {
	border: 2px solid #fff;
}
.level {
	position: absolute;
	top: 20px;
	left: 50%;
	transform: translate(-50%);
	color: rgba(255,255,255,0.5);
	font-size: 2em;
	font-family: 'Roboto', sans-serif;
}
.coinSource {
	position: absolute;
	bottom: 40px;
	left: 50%;
	transform: translate(-50%);
	height: 400px;
	width: 400px;
	z-index: 100000;
	user-select: none;
	pointer-events: none;
}
.awardCounter {
	position: relative;
	width: 100%;
	display: inline-block;
	text-align: center;
	font-size: 2em;
	font-weight: bold;
}
.paidInFull {
	background: rgba(229, 249, 141, 1) !important;
	color: #000 !important;
}
</style>

</head>

<body translate="no">
  <svg viewBox="0 0 100 100" id="wordscapesGame">
	<circle class="circleShadow" cx="50" cy="50" r="38" />
	<circle class="circleBG" cx="50" cy="50" r="40" />
	<path class="connector" d="" stroke-linecap="round" stroke-width="4" fill="none" />
	<path class="connectedLetters" d="" stroke-linecap="round" stroke-width="4" fill="none" />
	<g id="gameArea">
		<g class="letter" data-letter="G" data-letter-id="G64311bb0-cb21-4dbb-bfe7-13607d65c2fb" transform="translate(77, 50)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">G</text>
		</g>
		<g class="letter" data-letter="R" data-letter-id="R510ca42b-73a7-4e59-823b-b8eb7fd75d4a" transform="translate(63.5, 73.383)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">R</text>
		</g>
		<g class="letter" data-letter="E" data-letter-id="E3e5c2516-d71b-4993-a7b5-79d11ddff267" transform="translate(36.5, 73.383)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">E</text>
		</g>
		<g class="letter" data-letter="E" data-letter-id="E8dfa375c-dc14-4942-ad07-1f8f29766f8c" transform="translate(23, 50)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">E</text>
		</g>
		<g class="letter" data-letter="T" data-letter-id="T9bc63092-9370-48a2-baa4-92dbffd4b365" transform="translate(36.5, 26.617)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">T</text>
		</g>
		<g class="letter" data-letter="A" data-letter-id="A6a8d5be2-ec87-4a9f-b83d-cac1c238ee98" transform="translate(63.5, 26.617)">
			<circle class="letterCircle" cx="0" cy="0" r="11" fill="rgba(255,255,255,0.5)"></circle>
			<text class="letterText" x="0" y="2" font-size="16" text-anchor="middle" dominant-baseline="middle">A</text>
		</g>
	</g>
</svg>
<button class="shuffle" title="Rearrange Letters">
	<svg viewBox="0 0 24 24" width="100%" height="100%" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round">
		<polyline points="16 3 21 3 21 8"></polyline>
		<line x1="4" y1="20" x2="21" y2="3"></line>
		<polyline points="21 16 21 21 16 21"></polyline>
		<line x1="15" y1="15" x2="21" y2="21"></line>
		<line x1="4" y1="4" x2="9" y2="9"></line>
	</svg>
</button>

<!-- <button class="awards" title="Awards">
	<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round">
		<circle class="coinDestination" cx="12" cy="8" r="7"></circle>
		<polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"></polyline>
	</svg>
</button> -->


<span class="currentWord"></span>

<div id="menuCheck">
	<!-- Hack these to act like a button -->
	<input id="menuCheckBox" type="checkbox" name="Menu Checkbox" value="menuCheckBox">
	<label for="menuCheckBox" title="Toggle Menu">
		<span class="wordsComplete">
			<span class="foundWords">0</span>
			<hr />
			<span class="totalWords"></span>
		</span>
	</label>
	<!-- Your menu stuff. Buttons and such -->
	<div class="menu">
		<div class="header">All possible<br />3+ letter words</div>
		<div class="menuInner">
		</div>
	</div>
</div>


<div id="menuCheckL">
	<!-- Hack these to act like a button -->
	<input id="menuCheckBoxL" type="checkbox" name="Menu Checkbox" value="menuCheckBox">
	<label for="menuCheckBoxL" class="awards" title="Toggle Menu">
		<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="coinDestination">
		<circle cx="12" cy="8" r="7"></circle>
		<polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"></polyline>
	</svg>
	</label>
	<!-- Your menu stuff. Buttons and such -->
	<div class="menu">
		<div class="header">Awards</div>
		<div class="menuInner">
			<div class="menuInstructions">
				You have earned
				<br/>
				<span class="awardCounter">0</span>
				<br/>
				coins!
				<br/>
				<br/>
				You can use coins to show hints!
			</div>
		</div>
	</div>
</div>

<button class="newGame" title="Start a New Game">New Game</button>

<div class="level" title="Level">1</div>

<div class="coinSource"></div>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vectorfetti.min.js"></script>
      <script >
let MOUSEDOWN = false;
let selectedLetters = [];
let validWords = [];
let validWordsClone = validWords;
let points;
let wordStarted = false;
let foundWords = 0;
let currentWord = '';
// track x and y in an svg
let pt = new DOMPoint();
let cx,cy;

// Set up game
async function gameSetup(word) {
	// Clear out stuff
	resetSelection();
	validWords = [];
	validWordsClone = [];
	foundWords = 0;
	currentWord = '';

	// Clear all buttons from menuInner
	const menuInner = document.querySelector(".menuInner");
	while (menuInner.firstChild) {
		menuInner.removeChild(menuInner.firstChild);
	}

	document.querySelector(".foundWords").textContent = "0";
	document.querySelector(".to.........完整代码请登录后点击上方下载按钮下载查看

网友评论0