JS小游戏-像素鸟#源码#Javascript

1、游戏图片

像素鸟小游戏
在这里插入图片描述

2、HTML部分

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            margin: 0;
        }
        .game{
            position: relative;
            width: 800px;
            height: 600px;
            margin: 0 auto;
            overflow: hidden;
        }
        .sky {
            position: absolute;
            width: 200%;
            height: 100%;
            background-image: url('./img/sky.png');
            margin: 0 auto;
        }

        .game .bird {
            background: url("./img/bird.png");
            position: absolute;
            width: 33px;
            height: 26px;
            left: 150px;
            top: 150px;
        }

        .game .bird.swing1{
            background-position: -8px -10px;
        }

        .game .bird.swing2{
            background-position: -60px -10px;
        }

        .game .bird.swing3{
            background-position: -113px -10px;
        }
        .pipeDown{
            position: absolute;
            background-image: url('./img/pipeUp.png');
            width: 52px;
            height: 100px;
            left: 500px;
            bottom: 112px;
        }

        .pipeUp{
            position: absolute;
            background-image: url('./img/pipeDown.png');
            background-position: bottom;
            width: 52px;
            height: 100px;
            left: 500px;
            top: 0;
        }
        .ground{
            position: absolute;
            background-image: url('./img/land.png');
            width: 200%;
            height: 112px;
            left: 0;
            bottom: 0;
        }

        .score{
            position: absolute;
            width: 100px;
            height: 36px;
            background-color: lightblue;
            right: 0;
            top: 0;
            text-align: center;
            line-height: 36px;
            font-size: 24px;
            z-index: 100;
        }
        p{
            text-align: center;
        }


    </style>
</head>
<body>
    <div class="game">
        <div class="sky"></div>
        <div class="bird swing1"></div>
        <div class="ground"></div>
        <div class="score">0</div>
    </div>
    <p>按w或者按上开始游戏</p>

    <script src="./JS/Rectangle.js"></script>
    <script src="./JS/Sky.js"></script>
    <script src="./JS/Land.js"></script>
    <script src="./JS/Bird.js"></script>
    <script src="./JS/Pipe.js"></script>
    <script src="./JS/Game.js"></script>
</body>
</html>

3、JS部分

baseGame class
/**
 * 基础的游戏类
 * 属性: 宽度 高度、横坐标、纵坐标、横向速度、纵向速度、对应的dom元素
 */
class Rectangle {
    constructor(width,height,x,y,vx,vy,dom){
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
        this.dom = dom;
        this.render();
    }

    /**
     * 渲染
     */
    render(){
        this.dom.style.width = this.width + "px";
        this.dom.style.height = this.height + "px";
        this.dom.style.left = this.x + "px";
        this.dom.style.top = this.y + "px";
    }
    onMove(){

    }
    /**
     *  在duration时间下物体移动
     * @param {number} duration  间隔
     */
    move(duration){
        this.x += this.vx * duration;
        this.y += this.vy * duration;
        if(this.onMove) this.onMove();
        this.render();
    }
}
sky ground class
const skyDom = document.querySelector('.sky');
skyStyle = getComputedStyle(skyDom);
const widthSky = parseFloat(skyStyle.width);
const heightSky = parseFloat(skyStyle.width);

class Sky extends Rectangle{
    constructor(){
        super(widthSky, heightSky, 0, 0, -100, 0, skyDom);
    }
    onMove(){
        if(this.x <= -widthSky / 2) {
            this.x = 0;
        }
    }
}
const landDom = document.querySelector('.ground');
landStyle = getComputedStyle(landDom);
const widthLand = parseFloat(landStyle.width);
const heightLand = parseFloat(landStyle.width);


class Land extends Rectangle{
    constructor(){
        super(widthLand, heightLand, 0, 488, -100, 0, landDom);
    }

    onMove(){
        if(this.x <= -widthLand / 2) {
            this.x = 0;
        }
    }
}
bird class
const birdDom = document.querySelector('.bird');
birdStyle = getComputedStyle(birdDom);
const widthBird = parseFloat(birdStyle.width);
const heightBird = parseFloat(birdStyle.height);

class Bird extends Rectangle{
    gravity = 1000;   
    constructor(){
        super(widthBird, heightBird, 150, 200, 0, 100, birdDom);
        this.swingState = 1;
        this.bindEvent();
    }
    
    // 綁定鼠標按下
    bindEvent(){
        document.addEventListener('keydown', (e) => {
            if(e.key === 'w' || e.key === 'ArrowUp'){
                this.vy += -550;
            }
        })
        this.startSwing();
    }

    // 小鳥扇翅膀
    startSwing(){
        if(this.timer){
            return ;
        }
        this.timer = setInterval( () => {
            birdDom.classList.remove('swing'+this.swingState);
            this.swingState = (++this.swingState % 3) + 1;
            birdDom.classList.add('swing'+this.swingState);
        },300)
    }
    stopSwing(){
        clearInterval(this.timer);
        this.timer = null;
    }

    onMove(){
        if(this.y >= 463) {
            this.y = 463;
            this.vy =0;
        }
        if(this.y <= 0 ){
            this.y = 0;
            this.vy = 0;
        }
    }

    move(duration){
        super.move(duration);
        this.vy += this.gravity * duration;
    }

}
pipe class
const game = document.querySelector('.game');
const gameWidth = game.clientWidth;
class Pipe extends Rectangle{
    isExited = true;
    constructor(height, top, speed, dom){
        super(52, height, gameWidth, top, speed, 0, dom);
    }
    onMove(){

        if(this.x < -this.width){
            this.dom.remove();
            this.isExited = false;
        }
    }

    
}

function getRandomNumber(min, max){
    return Math.floor(Math.random() * (max - min)) + min;
}

class PipePare{
    stopTimer = null;
    
    constructor(speed){
        this.up = document.createElement('div');
        this.down = document.createElement('div');
        this.up.classList.add('pipeUp');
        this.down.classList.add('pipeDown');
        game.appendChild(this.up);
        game.appendChild(this.down);

        this.spaceHeihgt = 150;  // 柱子之間的空隙 
        const fristPipeHeight = getRandomNumber(0, 488-150);

        this.upPipe = new Pipe(fristPipeHeight, 0, speed, this.up);
        this.downPipe = new Pipe(338 - fristPipeHeight, 150 + fristPipeHeight, speed, this.down);
    }
    stop(){
        if(this.stopTimer){
            clearInterval(this.stopTimer);
            this.stopTimer = null;
        }
        this.down.remove();
        this.up.remove();
    }

    move(duration){
        this.stopTimer = setInterval( () => {
            this.upPipe.move(duration);
            this.downPipe.move(duration);
        },10)
    }

    isCollision(bird){
        const birdStyle = getComputedStyle(document.querySelector('.bird'))
        let y = Number.parseInt(birdStyle.top);
        if(this.upPipe.x < bird.x + bird.width && this.upPipe.x > bird.x){
            return y < this.upPipe.height || y + bird.height > this.upPipe.height + this.spaceHeihgt;
        }
    }
}

class GamePipePair{
    pipeTimer = null;
    pipeArr = [];  // 用于显示的管道数组
    // 记录小鸟越过的数组
    scoreArr = [];
    constructor(speed){
        this.speed = speed;
        this.pair = new PipePare(speed);
        this.init();
    }

    init(){
        this.pipeTimer = setInterval( ()=> {
            let tmp = new PipePare(this.speed);
            tmp.move(0.01);
            this.pipeArr.push(tmp);
            this.scoreArr.push(tmp);
        }, 2000) 
    }

    getScore(bird){
        return this.scoreArr.filter(item => item.upPipe.x <= bird.x).length;
    }

    stop(){
        this.pipeArr.forEach(item => {
            item.stop();
        })
        if(this.pipeTimer){
            clearInterval(this.pipeTimer);
            this.pipeTimer = null;
        }
    }

    collisionDetection(bird){  // 小鸟对象传入
        this.pipeArr = this.pipeArr.filter(item => item.upPipe.isExited); // 过滤掉了不存在的
        // 检查小鸟是否碰撞到柱子
        for(let i = 0 ;i < this.pipeArr.length;i++){
            if(this.pipeArr[i].isCollision(bird)){
                return true;
            }
        }
        return false;
    }
    
}
game class
class Game {
    score = 0;
    land;
    sky;
    bird;
    backgroundTimer = null;
    pipeController = null;
    
    constructor(){
        this.land = new Land();
        this.sky = new Sky();
        this.bird = new Bird();
        this.state = 0;   // 0 遊戲結束  1遊戲開始進行中
        this.init();   
    }

    init(){
        document.onkeydown =  (e) => {
            if((e.key === 'w' || e.key === 'ArrowUp') && this.state === 0){
                console.log('開始遊戲');
                this.state = 1;
                this.startGame();
            }
        }
    }

    startGame(){
        this.pipeController = new GamePipePair(-100);
        if(this.backgroundTimer) return ;
        this.backgroundTimer = setInterval(() => {
            this.land.move(0.01);
            this.sky.move(0.01);
            this.bird.move(0.01);
            this.updateScore();
            if(this.pipeController){
                if(this.pipeController.collisionDetection(this.bird)){
                    this.endGame();
                    console.log('game ended');
                }
            }
        }, 10)


    }

    updateScore(){
        const score = document.querySelector('.score');
        this.score = this.pipeController.getScore(this.bird)
        score.innerHTML = this.score;
    }

    endGame(){
        if(this.backgroundTimer && this.state === 1){
            this.pipeController.stop();
            this.state = 0;
            this.bird.stopSwing();
            clearInterval(this.backgroundTimer);
            this.backgroundTimer = null;
            document.onkeydown = null;
            if(confirm(`游戏结束!! 
                你最后的得分是${this.score}分
                你想要再玩一局嘛 想玩点确定哦!!!
                `)){
                    this.init();
                }
        }
    }

}

const birdGame = new Game();

4、源码+静态资源

像素鸟源码地址

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android O 适配详细指南

NotificationChannel channel new NotificationChannel(mChannelId, name, NotificationManager.IMPORTANCE_DEFAULT); mNotificationManager.createNotificationChannel(channel); } } // 创建通知传入channelId NotificationCompat.Builder builder new NotificationCompat…

【python包安装】手动安装libmr

遇到问题 再导入libmr模块时&#xff0c;导入失败 尝试使用pip install libmr安装&#xff0c;安装失败 查询原因是windows上pip安装找不到库&#xff0c;只能采取手动安装。 解决方法 下载libMR库文件 安装方法可以查看README文档 安装libmr之前需要安装Microsoft C14或…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-23卷积神经网络LeNet

23卷积神经网络LeNet import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as plt# 定义一个卷积神经网络 net nn.Sequential(nn.Conv2d(1, 6, kernel_size5, padding2), # 卷积层1&#xff1a;输入通道数1&#xff0c;输出通道数6&#x…

2024 Testing Expo China – Automotive I 风丘与您相约上海世博馆

2024汽车测试及质量监控博览会&#xff08;中国&#xff09;——&#xff08;Testing Expo China – Automotive&#xff09;是面向整车、零部件和系统开发的各种技术和服务的盛会&#xff0c;展示了汽车测试、开发和验证技术的各个方面&#xff0c;每年在上海举行&#xff0c;…

如何识别商业电子邮件诈骗

复制此链接到微信打开阅读全部已发布文章 不要关闭它标签&#xff01;我知道很少有词组比商业、电子邮件和妥协更无趣。 但这不是一篇无聊的文章&#xff1a;这是一篇关于电子邮件骗子的文章&#xff0c;根据联邦调查局的说法&#xff0c;他们每年通过诈骗人们赚取 260 亿美元…

Java程序之动物声音“模拟器”

题目&#xff1a; 设计一个“动物模拟器”&#xff0c;希望模拟器可以模拟许多动物的叫声和行为&#xff0c;要求如下&#xff1a; 编写接口Animal&#xff0c;该接口有两个抽象方法cry()和getAnimalName()&#xff0c;即要求实现该接口的各种具体的动物类给出自己的叫声和种类…

33.LengthFieldBasedFrameDecoder四个参数

第一种方式: 消息的长度和内容一起发送。 数据分为两部分,一部分是数据的长度,另一部分是数据内容本身。 构造方法参数 lengthFieldOffset 表示整个消息体内,消息长度字段的偏移量。就是记录消息长度的字节的开始位置。 lengthFieldLength 表示长度字段的长度。就是用…

02_ESP32+MicroPython 点亮LED灯

书接第1篇《01_ESP32 MicroPython开发环境搭建_eps32开发板-CSDN博客》 想要让一个引脚输出高电平&#xff0c;只需要找到对应的GPIO然后通过on()或者value(1)操作就可以&#xff0c;同理如果想要输出低电平让LED灯灭&#xff0c;只需要调用off()或者value(0)就行。 一、点亮…

Android开发实用必备的几款插件,提高你的开发速度

1.GsonFormat 使用方法&#xff1a;快捷键AltS也可以使用AltInsert选择GsonFormat&#xff0c;作用&#xff1a;速将json字符串转换成一个Java Bean&#xff0c;免去我们根据json字符串手写对应Java Bean的过程。 2.ButterKnife Zelezny 又叫黄油刀 使用方法&#xff1a;CtrlS…

Android面试题之动画+事件处理篇

1、Android 中的动画有哪几类 帧动画、补间动画、属性动画 2、动画能组合在一起使用么&#xff1f; 可以将动画组合在一起使用AnimatorSet&#xff0c; AnimatorSet.play() 播放当前动画的同时可以 .with() &#xff1a;将现有动画和传入的动画同时执行 .after() &#xff1a…

Android:知道类加载过程面试还是卡壳?干货总结,一网打净“类”的基础知识!

多线程进行类的初始化会出问题吗&#xff1f; 类的实例化触发时机。 <clinit>()方法和<init>()方法区别。 在类都没有初始化完毕之前&#xff0c;能直接进行实例化相应的对象吗? 类的初始化过程与类的实例化过程的异同&#xff1f; 一个实例变量在对象初始化…

禅道身份认证绕过漏洞(QVD-2024-15263)复现

禅道项目管理系统在开源版、企业版、旗舰版的部分版本中都存在此安全漏洞。攻击者可利用该漏洞创建任意账号实现未授权登录。 1.漏洞级别 高危 2.漏洞搜索 fofa: title"禅道"3.影响范围 v16.x < 禅道 < v18.12 &#xff08;开源版&#xff09; v6.x <…

自动驾驶仿真测试用例(完善版本)

进一步完善上述的测试用例&#xff0c;并根据不同的测试准备、车辆准备、车辆状态、车辆场景、车辆执行、可变因素、具体信号状态、通过标准和预期标准来详细描述每个测试用例。 用例编号测试类型测试项目测试描述车辆准备车辆状态车辆场景车辆执行可变因素具体信号状态通过标准…

Android应用--简、美音乐播放器添加电话监听

3. 控制音量 4. 获取专辑图片 5. 在线下载歌词 6. 在线搜索音乐 7. 在线下载音乐 8. 实现有趣功能–甩歌 9. 界面美化–实现专辑倒影 10.实现左右界面切换 11.实现在通知栏显示播放状态 12.实现音乐播放的桌面小控件 暂时想到这些功能&#xff0c;如果朋友们有什么建…

Pikachu靶场--越权漏洞

参考借鉴 pikachu之越权漏洞_pikachu越权漏洞-CSDN博客 水平越权 需要输入username和password进行登录 查看提示&#xff0c;获取username和password 输入其中一组账号信息进行登录 可以查看到个人信息 在URL中更改username的值-->回车 成功越权&#xff0c;登录到其他账号…

2024-06-23 编译原理实验4——中间代码生成

文章目录 一、实验要求二、实验设计三、实验结果四、附完整代码 补录与分享本科实验&#xff0c;以示纪念。 一、实验要求 在词法分析、语法分析和语义分析程序的基础上&#xff0c;将C−−源代码翻译为中间代码。 要求将中间代码输出成线性结构&#xff08;三地址代码&#…

CTFHUB-SSRF-POST请求

通过file协议访问flag.php文件内容 ?urlfile:///var/www/html/flag.php 右键查看页面源代码 需要从内部携带key发送post数据包即可获得flag ?urlhttp://127.0.0.1/flag.php 得到了key 构造POST请求数据包&#xff0c;进行url编码&#xff08;新建一个txt文件&#xff0c;…

【vue3|第12期】Vue3的Props详解:组件通信

日期&#xff1a;2024年6月19日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

微服务——重复消费(幂等解决方案)

目录 一、唯一ID机制二、幂等性设计三、状态检查机制四、利用缓存和消息队列五、分布式锁总结 在微服务中&#xff0c;防止重复消费的核心思想是通过设计使得操作一次与多次产生相同的效果&#xff0c;并为每次操作生成唯一的ID。这样&#xff0c;即使在消息被重复发送的情况下…

Stable Diffusion 插件安装与推荐,助力你的AI绘图

在上一篇文章我们安装了Stable Diffusion &#xff0c;这篇文章我们来安装Stable Diffusion的插件 Stable Diffusion的插件是绘画中重要的一环&#xff0c;好的插件可以让你的绘画更加得心应手 中英双语插件 为什么要安装中英双语插件呢&#xff0c;不能只安装中文插件吗&…