【最近抖音上元宇宙虚拟项目七国争霸,直播互动游戏源码解析】

最近抖音上元宇宙虚拟项目七国争霸,直播互动游戏,用户进入直播间可以发送弹幕互动,可能因为疫情大家憋在家无聊,直播间人数有5000多人,使用OBS做无人直播,不仅不会被限流,一天轻松赚个几百块也是玩一样。

源码下载位置:https://code.data5u.com/code/detail-624.html

雄争霸包括七个国家:齐、楚、燕、韩、赵、魏、秦。游戏每10分钟会进行一场,结束后会有战绩排行榜,宣布哪个国家是老大。

入直播间的用户,发送国家名字(齐楚燕韩赵魏秦)即可加入对应的国家,成为一个小士兵,然后开始随即移动开疆拓土。小士兵所到位置自动变成本国封土。拓土最多的士兵,会被封为国王,在所在的国家用一个大头像表示。如果国王被吃掉了,那么灭国。

兵可以发送小心心进行加速拓土,发送啤酒开启多个分身,发送棒棒糖可以给本国开启无敌金身10次(不会灭国)。

类似的弹幕互动游戏有挤地铁、广场舞、舞厅蹦迪、冲马桶、猜成语、猜歌名、大鱼吃小鱼等。

在这里插入图片描述

七雄争霸-七国争霸-齐楚燕韩赵魏秦

下面提供代码解析,共有三个模块:API接口、前端、采集端。

前端代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>V1</title>
		<link rel="stylesheet" href="css/index.css" media="all" />
		<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
		<script type="text/javascript" src="plugin/anime/lib/anime.min.js"></script>
	</head>
	<body style="padding: 0; margin: 0; width: 100%; height: 100vh; overflow: hidden;">
		<div class="bg-blur"></div>
		<div id="gezi"></div>
		<canvas id="canvas" width="300" height="150"></canvas>
		<div class="content">
			
			<div id="debugarea">
				<button id="start">开始</button>
				<button id="come_qi">齐国</button>
				<button id="come_chu">楚国</button>
				<button id="come_yan">燕国</button>
				<button id="come_han">韩国</button>
				<button id="come_zhao">赵国</button>
				<button id="come_wei">魏国</button>
				<button id="come_qin">秦国</button>
				<button id="fenshen">随机分身</button>
				<button id="jiasu">随机加速</button>
				<button id="wd_qin">秦国无敌10次</button>
				<button id="add_time">延时1分钟</button>
			</div>
			
			<div id="winnerCard" style="display: none; font-size: 200px; text-align: center; background: url(./img/bg/resbg.png); width: 400px; height: 700px; box-shadow: 5px 3px 20px 4px #888888; z-index: 9999; position: absolute; left: calc( 50% - 200px ); top: calc( 50% - 350px );">
				<div style="position: absolute; left: 100px;">
					<span id="child0" style="position: absolute; font-size: 80px; line-height: 80px; top: 70px; left: 60px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 200px;" src="./img/res/1.png"/>
				</div>
				
				<div style="position: absolute; left: 40px; top: 160px;">
					<span id="child1" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				<div style="position: absolute; left: 240px; top: 160px;">
					<span id="child2" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				
				<div style="position: absolute; left: 40px; top: 280px;">
					<span id="child3" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				<div style="position: absolute; left: 240px; top: 280px;">
					<span id="child4" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				
				<div style="position: absolute; left: 40px; top: 400px;">
					<span id="child5" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				<div style="position: absolute; left: 240px; top: 400px;">
					<span id="child6" style="position: absolute; font-size: 50px; line-height: 50px; top: 130px; left: 35px; font-family: '楷体'; font-weight: 700; text-shadow: 1px 2px red;"></span>
					<img style="width: 120px;" src="./img/res/2.png"/>
				</div>
				
			</div>
			
			<div id="model" style="display: none;">
				<div class="aFishModel" data-level="0" style="will-change: left,top; position: absolute; text-align: center; align-items: center; display: flex; flex-direction: column; flex-wrap: wrap; z-index: 1;">
					<p class="info" style="background-color: #FFFFFF; font-size: 12px; max-width: 300px; min-width: 70px; left: 5px; border: 1px solid #000000; overflow-wrap: normal; position: absolute; top: -40px; z-index: -1;"></p>
					<img class="headimg" src="" style="z-index: 9;box-shadow: rgb(0, 0, 0) 3px 3px 6px;" />
					<p class="headfont" style="display: none; line-height: 60px; width: 60px; height: 60px; border-radius: 30px;z-index: 9;position: absolute;background-color: #fff;font-size: 8px;	color: #000; word-wrap: break-word;"></p>
				</div>
			</div>
			
			<div id="message" style="position: absolute; top: 100px; text-align: center; width: 100%;">
				<div style="display: none; font-size: 30px; font-stretch: unset; font-weight: bolder; word-spacing: 20px; filter: opacity(0.3);">七雄争霸</div>
				<div style="font-size: 46px; word-spacing: 20px; filter: opacity(0.4); margin-top: 20px" id="timeleft"></div>
				<marquee id="eatmsg" style="position: absolute; top: -90px; left: 0; color: #676767;"></marquee>
			</div>
			
			<div id="container" style="display: flex; flex-direction: row; height: 100vh;  background: url(img/bg/2.jpg);"></div>
			
		</div>

		<script type="text/javascript" src="js/util.js"></script>
		<script type="text/javascript" src="js/config.js"></script>
		<script type="text/javascript" src="js/v1.js"></script>
		<script type="text/javascript" src="js/control.js"></script>
		<script type="text/javascript" src="js/canvas.js"></script>
		
	</body>
</html>

画图控制控制代码:

//获取canvas元素
var canvas = document.querySelector("canvas");
//canvas元素有一个getContext()的方法,这个方法是用来获得渲染上下文和它的绘画功能。
//此案例是对于2D图像而言,用法如下所示
var ctx = canvas.getContext("2d");
//获取button元素
var bn = document.querySelector("button");
//设置边线颜色
ctx.strokeStyle="red";
//设置一个bool值,值为true 代表擦除,值为false代表绘制,默认false
var bool=false;
//给画布添加一个鼠标按下的事件监听
canvas.addEventListener("mousedown",mouseHandler);
//给按钮添加一个鼠标点击的事件监听
bn.addEventListener("click",clickHandler);

function clickHandler(e){
	//当按钮被点击时,为擦除功能,切换bool值和对应的按钮内容
	bool = !bool;
	if(bool){
		bn.textContent="绘制";
	}else{
		bn.textContent="擦除";
	}
}

function mouseHandler(e){
	if(!bool){
	//当bool为false时,执行绘制功能,否则擦除功能。
		drawLine(e);
	}else{
		clearLine(e);
	}
}

function clearLine(e){
	if(e.type === "mousedown"){
		//设置一个清除矩形,左上角坐标为前面两个参数,
		//第三个参数是清除矩形的宽度,最后一个参数是清除矩形的高度,都是以像素为单位。
		//e.offsetX,e.offsetY 为当前鼠标按下的坐标
		ctx.clearRect(e.offsetX,e.offsetY,70,70);
		//添加两个事件监听
		canvas.addEventListener("mousemove",mouseHandler);
		canvas.addEventListener("mouseup",mouseHandler);
	}else if(e.type === "mousemove"){
		ctx.clearRect(e.offsetX,e.offsetY,70,70);
	}else if(e.type === "mouseup"){
		//鼠标抬起,清除监听功能
		canvas.removeEventListener("mousemove",mouseHandler);
		canvas.removeEventListener("mouseup",mouseHandler);
	}
}

function drawLine(e){
	if(e.type === "mousedown"){
		//起始一条路径,或者重绘当前路径
		ctx.beginPath();
		//起始点
		ctx.moveTo(e.offseeeetX,e.offsetY);
		canvas.addEventListener("mousemove",mouseHandler);
		canvas.addEventListener("mouseup",mouseHandler);
	}else if(e.type === "mousemove"){
		//终点
		ctx.lineTo(e.offsetX,e.offsetY);
		//开始绘制
		ctx.stroke();
	}else if(e.type === "mouseup"){
		canvas.removeEventListener("mousemove",mouseHandler);
		canvas.removeEventListener("mouseup",mouseHandler);
	}
}

配置代码:

var config = {
	bg: 'img/bg/1.jpg',
	animatesize: 5,
	
	game_start: false,
	timeIt: null, // 倒计时IT
	
	random_head_size: 19, // 虚拟头像个数
	name_show_time: 3000, // 名字显示时间
	
	war_time: 30, // 单位秒
	
	use_name_no_avatar: false, // 
	
	debug: true,
	
	// 加速礼物:小心心
	jiasu_gift: 'webcast.douyinpic.com/img/webcast/0ea40b8376ef8157791b928a339ed9c9~tplv-obj.png', 
	add_speed: 10, // 一个小心心加速大小
	
	// 分身礼物:啤酒
	fenshen_gift: 'webcast.douyinpic.com/img/webcast/a24b3cc863742fd4bc3de0f53dac4487.png~tplv-obj.png', 
	
	// 无敌礼物:棒棒糖
	wd_gift: 'webcast.douyinpic.com/img/webcast/cadd229a47b7fad58ba021c7d4638516~tplv-obj.png', 
	wd_num: 10,
	
	maxWidth: $('body').width(),
	maxHeight: $('body').height(),
	
	msgTime: 6000, // 消息可以显示的时间
	
	listenIntervalTime: 200,

	head_size: 60, // 头像大小

	row_number: 40,
	col_number: 40,
	
	col_width: 0,
	col_height: 0,
	
	move_speed: 200,
	back_speed: 200,
	move_method: 'easeInOutQuad',
	move_direction: 'normal', // 可选 alternate、normal
	
	move_step: 1,
	back_step: 1,
	
	gezi: [],
	
	qi: {
		bgc: '#189432',
		rstart: 1,
		rend: 5,
		cstart: 1,
		cend: 7,
		rand: false,
		home: 0,
		name: '齐',
		wd: 0
	},
	chu: {
		bgc: '#1890FF',
		rstart: 23,
		rend: 29,
		cstart: 4,
		cend: 13,
		rand: false,
		home: 0,
		name: '楚',
		wd: 0
	},
	yan: {
		bgc: '#1fff32',
		rstart: 12,
		rend: 19,
		cstart: 1,
		cend: 6,
		rand: false,
		home: 0,
		name: '燕',
		wd: 0
	},
	han: {
		bgc: '#aaaa00',
		rstart: 1,
		rend: 6,
		cstart: 34,
		cend: 39,
		rand: false,
		home: 0,
		name: '韩'
	},
	zhao: {
		bgc: '#1bffff',
		rstart: 29,
		rend: 33,
		cstart: 24,
		cend: 34,
		rand: false,
		home: 0,
		name: '赵',
		wd: 0
	},
	wei: {
		bgc: '#f00002',
		rstart: 14,
		rend: 20,
		cstart: 32,
		cend: 38,
		rand: false,
		home: 0,
		name: '魏',
		wd: 0
	},
	qin: {
		bgc: '#f00fff',
		rstart: 9,
		rend: 15,
		cstart: 16,
		cend: 24,
		rand: false,
		home: 0,
		name: '秦',
		wd: 0
	},

	countryArr: ['齐', '楚', '燕', '韩', '赵', '魏', '秦'],

}

function initConfig() {
	// 初始化背景
	$('.bg-blur').css('background', 'url(' + config.bg + ')');
	
	// 初始化时间
	$('#timeleft').html( config.war_time + '秒' ).attr('data-left', config.war_time);
	
	// 初始化canvas
	$('canvas').css('width', config.maxWidth).css('height', config.maxHeight).css('position', 'absolute').css('left', '0').css('top', '0').css('z-index', '1');

	// 初始化格子
	var colWidth = config.maxWidth / config.row_number - 2;
	var colHeight = config.maxHeight /config.col_number;
	
	config.col_height = colHeight;
	config.col_width = colWidth;
	
	var colIndex = 1;
	
	for(var x = 0; x < config.row_number; x++) {
		var html = [];
		html.push('<div class="row row_' + x + '">');
		for(var y = 0; y < config.col_number; y++) {
			
			config.gezi.push(colIndex); // 把可用的格子存储起来
			
			html.push('<div data-row="' + x + '" data-col="' + y + '" data-index="' + (colIndex++) + '" class="col col_' + x + '_' + y + '" style="width: ' + colWidth + 'px; height: ' + colWidth + 'px;">');
			// if(config.debug) html.push(colIndex-1);
			html.push('</div>');
		}
		html.push('</div>');
		$('#gezi').append(html.join(''));
		
		// 判断上一个格子是否超过最大高度
		var lastTop = $('.col_' + x + '_0').offset().top;
		if( lastTop + colHeight > config.maxHeight ) {
			config.row_number = x - 1;
			
			$('.row_' + x + ' .col').each(function(){
				config.gezi.remove( parseInt($(this).attr('data-index')) );
				$(this).empty();
			})
			
			break;
		}
	}
	
	// 初始化七雄
	if( config.qi.rand ) {
		config.qi.cend = Math.ceil( config.qi.cend * Math.random() ) + 1;
		if( config.qi.cend < config.qi.cstart ) config.qi.cend = config.qi.cstart + 5;
		
		config.qi.rend = Math.ceil( config.qi.rend * Math.random() ) + 1;
		if( config.qi.rend < config.qi.rstart ) config.qi.rend = config.qi.rstart + 5;
	}
	
	var rx = config.qi.rstart + Math.ceil( (config.qi.rend - config.qi.rstart) / 2 );
	var ry = config.qi.cstart + Math.ceil( (config.qi.cend - config.qi.cstart) / 2 );
	config.qi.home = $('.col_' + rx + '_' + ry);
	config.qi.home.attr('data-home', '1');
	
	for( var row = config.qi.rstart; row < config.qi.rend; row++ ) {
		for( var col = config.qi.cstart; col < config.qi.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.qi.bgc).html('齐').attr('data-country', config.qi.name);
		}
	}
	if(config.debug) config.qi.home.css('background', '#fff');
	
	// 楚国,前6行最后7个
	
	if( config.chu.rand ) {
		config.chu.cend = Math.ceil( config.chu.cend * Math.random() ) + 1;
		if( config.chu.cend < config.chu.cstart ) config.chu.cend = config.chu.cstart + 5;
		config.chu.rend = Math.ceil( config.chu.rend * Math.random() ) + 1;
		if( config.chu.rend < config.chu.rstart ) config.chu.rend = config.chu.rstart + 5;
	}
		
	var rx = config.chu.rstart + Math.ceil( (config.chu.rend - config.chu.rstart) / 2 );
	var ry = config.chu.cstart + Math.ceil( (config.chu.cend - config.chu.cstart) / 2 );		
	config.chu.home = $('.col_' + rx + '_' + ry);
	config.chu.home.attr('data-home', '1');
	
	for( var row = config.chu.rstart; row < config.chu.rend; row++ ) {
		for( var col = config.chu.cstart; col < config.chu.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.chu.bgc).html('楚').attr('data-country', config.chu.name);
		}
	}
	if(config.debug) config.chu.home.css('background', '#fff');
	
	// 燕国,12-19行前3个
	if( config.yan.rand ) {
		config.yan.cend = Math.ceil( config.yan.cend * Math.random() ) + 1;
		if( config.yan.cend < config.yan.cstart ) config.yan.cend = config.yan.cstart + 5;
		config.yan.rend = Math.ceil( config.yan.rend * Math.random() ) + 1;
		if( config.yan.rend < config.yan.rstart ) config.yan.rend = config.yan.rstart + 5;
	}
		
	var rx = config.yan.rstart + Math.ceil( (config.yan.rend - config.yan.rstart) / 2 );
	var ry = config.yan.cstart + Math.ceil( (config.yan.cend - config.yan.cstart) / 2 );
	config.yan.home = $('.col_' + rx + '_' + ry);
	config.yan.home.attr('data-home', '1');
	
	for( var row = config.yan.rstart; row < config.yan.rend; row++ ) {
		for( var col = config.yan.cstart; col < config.yan.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.yan.bgc).html('燕').attr('data-country', config.yan.name);
		}
	}
	if(config.debug) config.yan.home.css('background', '#fff');
	
	// 韩国,7-13行中间6个
	if( config.han.rand ) {
		config.han.cend = Math.ceil( config.han.cend * Math.random() ) + 1;
		if( config.han.cend < config.han.cstart ) config.han.cend = config.han.cstart + 5;
		config.han.rend = Math.ceil( config.han.rend * Math.random() ) + 1;
		if( config.han.rend < config.han.rstart ) config.han.rend = config.han.rstart + 5;
	}
		
	var rx = config.han.rstart + Math.ceil( (config.han.rend - config.han.rstart) / 2 );
	var ry = config.han.cstart + Math.ceil( (config.han.cend - config.han.cstart) / 2 );
	config.han.home = $('.col_' + rx + '_' + ry);
	config.han.home.attr('data-home', '1');
			
	for( var row = config.han.rstart; row < config.han.rend; row++ ) {
		for( var col = config.han.cstart; col < config.han.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.han.bgc).html('韩').attr('data-country', config.han.name);
		}
	}
	if(config.debug) config.han.home.css('background', '#fff');
	
	// 赵国,最后4行中间6个
	if( config.zhao.rand ) {
		config.zhao.cend = Math.ceil( config.zhao.cend * Math.random() ) + 1;
		if( config.zhao.cend < config.zhao.cstart ) config.zhao.cend = config.zhao.cstart + 5;
		config.zhao.rend = Math.ceil( config.zhao.rend * Math.random() ) + 1;
		if( config.zhao.rend < config.zhao.rstart ) config.zhao.rend = config.zhao.rstart + 5;
	}

	var rx = config.zhao.rstart + Math.ceil( (config.zhao.rend - config.zhao.rstart) / 2 );
	var ry = config.zhao.cstart + Math.ceil( (config.zhao.cend - config.zhao.cstart) / 2 );
	config.zhao.home = $('.col_' + rx + '_' + ry);
	config.zhao.home.attr('data-home', '1');	
		
	for( var row = config.zhao.rstart; row < config.zhao.rend; row++ ) {
		for( var col = config.zhao.cstart; col < config.zhao.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.zhao.bgc).html('赵').attr('data-country', config.zhao.name);
		}
	}
	if(config.debug) config.zhao.home.css('background', '#fff');
	
	// 魏国,最后5行中间6个
	if( config.wei.rand ) {
		config.wei.cend = Math.ceil( config.wei.cend * Math.random() ) + 1;
		if( config.wei.cend < config.wei.cstart ) config.wei.cend = config.wei.cstart + 5;
		config.wei.rend = Math.ceil( config.wei.rend * Math.random() ) + 1;
		if( config.wei.rend < config.wei.rstart ) config.wei.rend = config.wei.rstart + 5;
	}
	
	var rx = config.wei.rstart + Math.ceil( (config.wei.rend - config.wei.rstart) / 2 );
	var ry = config.wei.cstart + Math.ceil( (config.wei.cend - config.wei.cstart) / 2 );
	config.wei.home = $('.col_' + rx + '_' + ry);
	config.wei.home.attr('data-home', '1');
			
	for( var row = config.wei.rstart; row < config.wei.rend; row++ ) {
		for( var col = config.wei.cstart; col < config.wei.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.wei.bgc).html('魏').attr('data-country', config.wei.name);
		}
	}
	if(config.debug) config.wei.home.css('background', '#fff');
	
	// 秦国,16-19行中间6个
	if( config.qin.rand ) {
		config.qin.cend = Math.ceil( config.qin.cend * Math.random() ) + 1;
		if( config.qin.cend < config.qin.cstart ) config.qin.cend = config.qin.cstart + 5;
		config.qin.rend = Math.ceil( config.qin.rend * Math.random() ) + 1;
		if( config.qin.rend < config.qin.rstart ) config.qin.rend = config.qin.rstart + 5;
	}
	
	var rx = config.qin.rstart + Math.ceil( (config.qin.rend - config.qin.rstart) / 2 );
	var ry = config.qin.cstart + Math.ceil( (config.qin.cend - config.qin.cstart) / 2 );
	config.qin.home = $('.col_' + rx + '_' + ry);
	config.qin.home.attr('data-home', '1');
	
	for( var row = config.qin.rstart; row < config.qin.rend; row++ ) {
		for( var col = config.qin.cstart; col < config.qin.cend; col++ ) {
			$('.col_' + row + '_' + col).css('background', config.qin.bgc).html('秦').attr('data-country', config.qin.name);
		}
	}
	if(config.debug) config.qin.home.css('background', '#fff');
	
}

window.onresize = function (){
	config.maxHeight = $('body').height() ;
	config.maxWidth = $('body').width() ;
}

initConfig();
  • 9
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DATA5U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值