基于three.js实现的点击盒子消除游戏

news2025/1/20 1:55:59

一.项目背景

大学时期参加了机器人协会,并有幸成为了视觉组组长,所以在新一届社团招新上做了一款趣味小游戏来吸引新生的眼球,让大家知道协会的视觉组。

二.代码展示

<!DOCTYPE html>
<html>
<head>
<style>
body {
    margin: 0;
    padding: 0;
    background-color: black;
    color:white;
    font-family: helvetica;
}
canvas {
    position: absolute;
}
.hud {
    position: absolute;
    margin-left: 1em;
}
.hit {
    font-weight: bold;
    color: red;
}
</style>
</head>
<body>
<script type="text/javascript" src="//wow.techbrood.com/libs/jquery/jquery-2.1.1.min.js"></script><div class="hud">
	<h1 align="center">机器人协会百团大战招新小游戏——眼花缭乱(视觉组制作)</h1>
    <h1 id="level"></h1>
    <p>点击方块,使它消失!!!</p>
    <p id="score"></p>
    <p>
        计时器:<span id="sp1"> 71</span></p>
</div>

<div id="webgl-container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js"></script>
<script>
var scene;
var cube;
var camera;
var renderer;
var clock;
var holder;
var intersects;
var particles = [];
var level = 1;
var totalLevels = 4;
var score = 0;
var totalTargets = 3;
var speed = 0.01;
var complete = false;
var comments = ["简单", "一般", "困难", "超困难"];
var myLevel = document.getElementById("level");
var myScore = document.getElementById("score");
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function myScene() {
    scene = new THREE.Scene();
    var light = new THREE.AmbientLight(0xffffff);
    var width = window.innerWidth;
    var height = window.innerHeight;
    camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
    camera.position.z = 18;
    renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
    });
    renderer.setSize(width, height);
    document.getElementById("webgl-container").appendChild(renderer.domElement);
    clock = new THREE.Clock();
    var sLight = new THREE.SpotLight(0xffffff);
    sLight.position.set(-100, 100, 100);
    scene.add(sLight);
    var aLight = new THREE.AmbientLight(0xffffff);
    scene.add(aLight);
}
function spinner() {
    var geometry = new THREE.BoxGeometry(1, 1, 1);
    var material = new THREE.MeshPhongMaterial({
        color: "hotpink",
        ambient: "hotpink"
    });
    var cube = new THREE.Mesh(geometry, material);
    cube.position.x = 10;
    var spinner = new THREE.Object3D();
    spinner.rotation.x = 6;
    spinner.add(cube);
    scene.add(spinner);
}
function addHolder() {
    holder = new THREE.Object3D();
    holder.name = "holder"
    for (var i = 0; i < totalTargets; i++) {
        var ranCol = new THREE.Color();
        ranCol.setRGB(Math.random(), Math.random(), Math.random());
        var geometry = new THREE.BoxGeometry(2, 2, 2);
        var material = new THREE.MeshPhongMaterial({
            color: ranCol,
            ambient: ranCol
        });
        var cube = new THREE.Mesh(geometry, material);
        cube.position.x = i * 5;
        cube.name = "cubeName" + i;
        var spinner = new THREE.Object3D();
        spinner.rotation.x = i * 2.5 * Math.PI;
        spinner.name = "spinnerName" + i;
        spinner.add(cube);
        holder.add(spinner);
    };
    scene.add(holder);
}
function addExplosion(point) {
    var timeNow = clock.getElapsedTime();
    for (var i = 0; i < 4; i++) {
        var geometry = new THREE.BoxGeometry(1, 1, 1);
        var material = new THREE.MeshBasicMaterial({
            color: 0x999999
        });
        var part = new THREE.Mesh(geometry, material);
        part.position.x = point.x;
        part.position.y = point.y;
        part.position.z = point.z;
        part.name = "part" + i;
        part.birthDay = timeNow;
        scene.add(part);
        particles.push(part);
    };
}
function animate() {
    requestAnimationFrame(animate);
    render();
}
function render() {
    holder.children.forEach(function(elem, index, array) {
        elem.rotation.y += (speed * (6 - index));
        elem.children[0].rotation.x += 0.01;
        elem.children[0].rotation.y += 0.01;
    });
    if (particles.length > 0) {
        particles.forEach(function(elem, index, array) {
            switch (elem.name) {
                case "part0":
                    elem.position.x += 1;
                    break;
                case "part1":
                    elem.position.x -= 1;
                    break;
                case "part2":
                    elem.position.y += 1;
                    break;
                case "part3":
                    elem.position.y -= 1;
                    break;
                default:
                    break;
            }
            if (elem.birthDay - clock.getElapsedTime() < -1) {
                scene.remove(elem);
                particles.splice(index, 1);
            }
        })
    };
    renderer.render(scene, camera);
}
function onDocumentMouseDown(event) {
    event.preventDefault();
    if (complete) {
        complete = false;
        score = 0;
        restartScene();
        return;
    }
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, camera);
    if (score < totalTargets) {
        holder.children.forEach(function(elem, index, array) {
            intersects = raycaster.intersectObjects(elem.children);
            if (intersects.length > 0 && intersects[0].object.visible) {
                intersects[0].object.visible = false;
                addExplosion(intersects[0].point);
                score += 1;
                if (score < totalTargets) {
                    myScore.innerHTML = "<span class='hit'>考验手速的时候到了!!!</span> Score: " + score + "/" + totalTargets;
                } else {
                    complete = true;
                    if (level < totalLevels) {
                        myScore.innerHTML = "<strong>你消灭了全部</strong> 点击屏幕进入下一等级 " + (level + 1) + ".";
                    } else {
                        myScore.innerHTML = "<strong>你胜利啦,快去找社团负责人领取奖品吧!</strong> ";
                        alert("你胜利啦,快去找社团负责人领取奖品吧!请点击刷新以重新开始游戏。");
                    }
                };
            }
        });
    }
}
function restartScene() {
    myScore.innerHTML = "";
    if (level < totalLevels) {
        speed += 0.005;
        totalTargets += 1;
        level += 1;
    } else {
        speed = 0.01;
        totalTargets = 3;
        level = 1;
    }
    myLevel.innerText = comments[level - 1] + ": Level " + level + " of " + totalLevels;
    scene.remove(holder);
    addHolder();
}
document.getElementById("webgl-container").addEventListener('mousedown', onDocumentMouseDown, false);
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    render();
}
window.onload = function() {
    myLevel.innerText = comments[level - 1] + ": Level " + level + " of " + totalLevels;
    myScene();
    addHolder();
    animate();
    window.addEventListener('resize', onWindowResize, false);
};
    var sp1 =document.getElementById("sp1").innerHTML;
    var time = setInterval(function () {
    	if(level===1&&sp1==71){
    		alert("请仔细观看左边的规则哦!!!熟悉规则后按确定开始游戏!!!")
    	}
    	if(sp1===0&&level!=1){
    		sp1=1;
    	}
    	sp1 = sp1-1;
        document.getElementById("sp1").innerHTML =sp1;
        if (sp1 ===0){
            alert("你失败了!");
        }
        if(sp1===0){
        	if(level ===1){
        		sp1=71;
        	}
        }
    },1000)
</script>
</body>
</html>

三.项目使用方法

桌面新建txt文本文件。
请添加图片描述
将代码复制到文本文件中。
请添加图片描述
修改文件后缀名。

请添加图片描述
双击文件就可以打开了,最好使用google浏览器,并且第一次打开速度比较慢。

四.项目展示

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/575807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python文件名字替换-优化SEO的必备技巧

Python文件名字替换-优化SEO的必备技巧 作为一名有10年Python编程经验的工程师&#xff0c;我深知文件名字替换在优化搜索引擎排名中占有重要的地位。本文将介绍如何使用Python进行文件名字替换以优化SEO&#xff0c;旨在为广大编程初学者提供有益的参考和指导。 什么是文件名…

零基础如何学习 Web 安全?

Web安全不仅是互联网的核心&#xff0c;而且还是云计算和移动互联网的最佳载体。对于信息安全从业者而言&#xff0c;Web安全是一个非常重要的研究课题之一。 Web应用是指采用B/S架构、通过HTTP/HTTPS协议提供服务的统称。随着互联网的广泛使用&#xff0c;社交网络、聊天工具…

小学妹刚毕业没地方住想来借宿?于是我连夜用Python给她找了个好房子,我真是太机智了

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 事情是这样的&#xff0c;小学妹刚毕业参加工作&#xff0c;人生地不熟的&#xff0c; 因为就在我附近上班&#xff0c;所以想找我借宿。。。 想什么呢&#xff0c;都不给住宿费&#xff0c;想免费住&#xff1f; 于是我用…

MySQL运维篇(二)

四.MyCat 4.1 MyCat概述 4.1.1 介绍 Mycat是开源的、活跃的、基于Java语言编写的数据库中间件。可以像使用mysql一样来使用 mycat&#xff0c;对于开发人员来说根本感觉不到mycat的存在。mycat不单只可以做MySQL的代理&#xff0c;其它常用的数据库也可以。 开发人员只需要…

基于springboot+Vue+ Element-Plus+mysql实现学生宿舍管理系统

基于springbootVue Element-Plusmysql实现学生宿舍管理系统 一、系统介绍二、功能展示1.登陆2、主页--学生3、主页--宿舍管理员4.学生管理--管理员5.宿管信息--管理员6.宿舍管理--管理员7.信息管理--管理员8.申请管理--管理员9.访客管理--管理员10.水电费管理--管理员11.卫生管…

AB Test数学原理及金融风控应用

1 什么是AB Test AB测试是一种常用的实验设计方法&#xff0c;用于比较两个或多个不同处理或策略的效果&#xff0c;以确定哪个处理或策略在某个指标上表现更好。在AB测试中&#xff0c;将随机选择一部分用户或样本&#xff0c;将其分为两个或多个组&#xff0c;每个组应用不同…

【Maven】单元测试、统计、覆盖率相关插件使用介绍

maven-surefire-plugin maven-surefire-plugin是maven执行单元测试的插件&#xff0c;不显性配置也可以直接使用。这个插件的surefire:test命令会默认绑定maven执行的test阶段。执行结束后&#xff0c;默认在target/surefire-reports目录下会生成txt和xml两种格式的结果&#…

接口测试-Mock测试方法

一、关于Mock测试 1、什么是Mock测试&#xff1f; Mock 测试就是在测试过程中&#xff0c;对于某些不容易构造&#xff08;如 HttpServletRequest 必须在Servlet 容器中才能构造出来&#xff09;或者不容易获取的比较复杂的对象&#xff08;如 JDBC 中的ResultSet 对象&#…

2023年电工杯B题问题二三思路讲解+创新点

问题二三解题思路 1.根据你们对数据的分析结果选取评价指标&#xff0c;从优先级、科学性、可操作性等方面论述其合理性&#xff0c;并构建评价指标体系&#xff1b; 2.建立数学模型&#xff0c;评价人工智能对大学生学习的影响&#xff0c;给出明确、有说服力的结论&#xf…

【SQL Server】数据库开发指南(六)索引和视图的使用技巧、方法与综合应用

本系列博文还在更新中&#xff0c;收录在专栏&#xff1a;#MS-SQL Server 专栏中。 本系列文章列表如下&#xff1a; 【SQL Server】 Linux 运维下对 SQL Server 进行安装、升级、回滚、卸载操作 【SQL Server】数据库开发指南&#xff08;一&#xff09;数据库设计 【SQL Se…

yolov5环境配置

阅读readme 阅读github上的yolov5的readme的环境配置&#xff0c;举例来说&#xff0c;yolov5_5.0要求如下。 删除原有出错误的环境 conda remove -n env_name --all -y 创建虚拟环境并指定python版本 conda create -n env_name python3.9 安装pytorch 查看显卡驱动 nvid…

​Kali-linux攻击路由器​

前面介绍的各种工具&#xff0c;都是通过直接破解密码&#xff0c;来连接到无线网络。由于在一个无线网络环境的所有设备中&#xff0c;路由器是最重要的设备之一。通常用户为了保护路由器的安全&#xff0c;通常会设置一个比较复杂的密码。甚至一些用户可能会使用路由器的默认…

Fourier分析入门——第10章——直接数据分析

目录 第10章 直接数据分析 10.1 引言 10.2 均值的方向和集中度(Mean direction and concentration about the mean) 10.3 假设检验(Hypothesis testing) 10.4 分组数据(Grouped data)及其与Fourier的关联 10.4.1 分组数据 10.4.2 分组数据与Fourier的关联 10.5 高次谐波…

解决未加载的符号文件

在连接器》命令行里输入&#xff1a;/INCLUDE:?warp_sizecudaatYAHXZ

浅谈智能疏散照明系统在体育场馆中的应用分析

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要&#xff1a;随着经济的发展和科技的进步&#xff0c;人们对电气智能化提出了更高的要求&#xff0c;使得电气智能化系统在智能建筑中的地位越来越重要。本文结合工程实例对体育场馆智能疏散照明系统的设计进行了…

Matlab:神经网络实现手写数字识别

如今人工智能发展的时代,机器学习有着不可或缺的地位,而其中最为突出的模型该属于神经网络。从提出神经网络开始,历经感知机、人工神经网络、BP神经网络、进化神经网络、卷积神经网络、图神经网络等,不断的深入到众多的研究领域中,比如利用神经网络训练参数、图像识别、文…

机试打卡 -12 滑动窗口最大值(优先队列堆)

我的思路1&#xff1a;队列&#xff0c;每次 出队入队&#xff0c;记录1个队列中的最大值索引&#xff0c;超时。。。 class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:nums_lenlen(nums)ans_list[]# 队列长度为kqueuenums[:k]# 队列最大…

基于GeoToolkit/INT实现二维等值线图绘制示例

继续在上一篇文章的基础上&#xff0c;利用相同的数据处理方法统一了地层数据和断层数据格式&#xff0c;本文主要基于GeoToolkit/INT组件&#xff0c;针对地质专业经常用到的地层数据解析和二维等值线&#xff08;等高或等深线&#xff09;可视化需求&#xff0c;本示例实现了…

Sqoop学习笔记

1 简介 Sqoop是Apache下的一款数据传输工具&#xff0c;用于Hadoop和关系型数据库等结构化数据存储之间的数据传输。 最新的稳定版本是1.4.7,Sqoop2 的最新版本是 1.99.7。请注意&#xff0c;1.99.7 与 1.4.7不兼容&#xff0c;且没有特征不完整&#xff0c;也并不打算用于生…

规则引擎入门-基于easy-rules

目录 概念理解实例和编码抽象出2条规则简单的规则引擎事实1的处理事实2的处理 easy-rules 规则的抽象和执行事实描述规则的抽象默认的规则 动态代理执行规则和动作规则的执行&#xff1a;org.jeasy.rules.core.DefaultRulesEngine#doFirepublic class RuleProxy implements Inv…