vue3+threejs新手从零开发卡牌游戏(十四):调整卡组位置,添加玩家生命值HP和法力值Mana信息

news2024/11/25 22:53:28

由于之前的卡组位置占了玩家信息的位置,所以这里将它调整到site区域:

修改game/site/p1.vue,在site右下角添加一个卡组区域:

// 初始化己方战域
const init = () => {
  let sitePlane = scene.getObjectByName("己方战域Plane")
  let planeWidth = sitePlane.userData.width
  let spaceX = (planeWidth - 5) / 4 // 设计一行有5个格子
  // console.log(123, spaceX)
  for (let i=0; i<5; i++) {
    let mesh = createWireframe()
    if (i == 0) {
      mesh.name = "场地"
    } else if (i == 1) {
      mesh.name = "己方怪兽区1"
      mesh.userData.empty = true // empty用来判断当前格子是否有空位
    } else if (i == 2) {
      mesh.name = "己方怪兽区2"
      mesh.userData.empty = true
    } else if (i == 3) {
      mesh.name = "己方怪兽区3"
      mesh.userData.empty = true
    } else if (i == 4) {
      mesh.name = "墓地"
    }
    if (i == 0 || i == 4) {
      mesh.position.set(-planeWidth/2 + 0.5, -0.65, 0)
    } else {
      mesh.position.set(-planeWidth/2 + 0.5, -0.7, 0)
    }
    mesh.translateX(spaceX * i + i)
    sitePlane.add(mesh)
  }
  for (let i=0; i<5; i++) {
    let mesh = createWireframe()
    if (i > 0 && i < 4) {
      if (i == 1) {
        mesh.name = "己方战术1"
      } else if (i == 2) {
        mesh.name = "己方战术2"
      } else if (i == 3) {
        mesh.name = "己方战术3"
      }
      mesh.position.set(-planeWidth/2 + 0.5, -2.2, 0)
      mesh.translateX(spaceX * i + i)
      sitePlane.add(mesh)
    }
    if (i == 4) {
      mesh.name = "卡组"
      mesh.position.set(-planeWidth/2 + 0.5, -2.15, 0)
      mesh.translateX(spaceX * i + i)
      sitePlane.add(mesh)
    }
  }
}

然后修改game/deck/p1.vue,将卡组位置调整到site卡组位置:

// 设置卡组位置
const setDeckPos = () => {
  nextTick(() => {
    let sitePlane = scene.getObjectByName("己方战域Plane")
    let siteDeckMesh = sitePlane.getObjectByName("卡组")
    let pos = siteDeckMesh.position
    siteDeckMesh.getWorldPosition(pos)
    deckGroup.position.set(pos.x, pos.y, pos.z)
    deckGroup.userData["position"] = pos
    deckGroup.scale.set(0.8, 0.8, 0.8) // 缩放
    console.log(222, siteDeckMesh)
  })
}

此时页面展示如下:

可以看到右下角区域已经空出来了,这个位置可以展示生命值等信息,这里直接用div+css写就可以,在game目录下新建player文件夹:

player/p1.vue代码如下:

<template>
  <div class="player-box">
    <!-- <p class="name">Name:<span>Player1</span></p> -->
    <div v-if="visible" class="info">
      <p class="HP">HP:<span>4000</span></p>
      <p class="Mana">Mana:<span>0</span>/<span>10</span></p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, onBeforeUnmount, watch, defineComponent, getCurrentInstance, nextTick } from 'vue'
import { useCommonStore } from "@/stores/common.ts"
import { Card } from "@/views/game/Card.ts"
import { CARD_DICT } from "@/utils/dict/card.ts"
import { transPos } from "@/utils/common.ts"

// 引入threejs变量
const {proxy} = getCurrentInstance()
const THREE = proxy['THREE']
const scene = proxy['scene']
const camera = proxy['camera']
const renderer = proxy['renderer']
const TWEEN = proxy['TWEEN']


const commonStore = useCommonStore()

const visible = ref(false)

const init = () => {
  visible.value = true
}

defineExpose({
  init,
})
</script>

<style lang="scss" scoped>
.player-box {
  position: fixed;
  bottom: 10px;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  width: 35vw;
  height: 14%;
  .info {
    position: relative;
    .HP {
      text-align: left;
      font-size: 18px;
      color: #fff;
      > span {
        font-size: 24px;
      }
    }
    .Mana {
      text-align: left;
      font-size: 16px;
      color: #fff;
      > span {
        font-size: 18px;
      }
    }
  }
}
</style>

此时页面展示如下:

附:

此时game/index.vue完整代码:

<template>
  <div ref="sceneRef" class="scene"></div>
  <!-- 玩家区 -->
  <Player ref="playerRef"/>
  <!-- 手牌 -->
  <Hand ref="handRef"/>
  <!-- 卡组 -->
  <Deck ref="deckRef"/>
  <!-- 战域 -->
  <Site ref="siteRef"/>
  <!-- 抽卡逻辑 -->
  <DrawCard ref="drawCardRef" :handRef="handRef"/>
  <!-- 对话框 -->
  <Dialog ref="dialogRef" @handToSite="handToSite" @onCancel="onCancel"/>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, onBeforeUnmount, watch, defineComponent, getCurrentInstance, nextTick } from 'vue'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // 轨道控制器
import { DragControls } from 'three/addons/controls/DragControls.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { useCommonStore } from "@/stores/common.ts"
import { transPos, editDeckCard, renderDeckText, renderSiteCardText } from "@/utils/common.ts"
import { Card } from "./Card.ts"
import { CARD_DICT } from "@/utils/dict/card.ts"
import Hand from "./hand/index.vue"
import Deck from "./deck/index.vue"
import Site from "./site/index.vue"
import Player from "./player/index.vue"
import DrawCard from "@/components/DrawCard.vue"
import Dialog from "@/components/Dialog.vue"

// 引入threejs变量
const {proxy} = getCurrentInstance()
const THREE = proxy['THREE']
const scene = proxy['scene']
const camera = proxy['camera']
const renderer = proxy['renderer']
const composer = proxy['composer']
const TWEEN = proxy['TWEEN']

// 后期处理
const renderPass = new RenderPass( scene, camera );
composer.addPass( renderPass );

// 
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

const commonStore = useCommonStore()


// 场景ref
const sceneRef = ref()
const playerRef = ref()
const siteRef = ref()
const handRef = ref()
const deckRef = ref()
const drawCardRef = ref()
const dialogRef = ref()

// 坐标轴辅助
const axesHelper = new THREE.AxesHelper(5);
// 创建轨道控制器
// const orbitControls = new OrbitControls( camera, renderer.domElement );
// 字体加载器
const fontLoader = new FontLoader();

onMounted(async () => {
  await initResource()
  initScene()
  initGame()

  // 鼠标按下
  window.addEventListener('touchstart', onMousedown)
  window.addEventListener('touchmove', onMousemove)
  // window.addEventListener('click', onMousedown)

  // 监听浏览器窗口变化进行场景自适应
  window.addEventListener('resize', onWindowResize, false);
})

// 资源加载
const initResource = () => {
  // 字体加载
  return new Promise((resolve, reject) => {
    // Microsoft YaHei_Regular
    // fonts/helvetiker_regular.typeface.json
    fontLoader.load('fonts/helvetiker_bold.typeface.json', (font: any) => {
      commonStore.loadFont(font)
      resolve(true)
    });
  })
}

// 初始化场景
const initScene = async () => {
  renderer.setSize( window.innerWidth, window.innerHeight );
  sceneRef.value.appendChild( renderer.domElement );
  scene.add(axesHelper)
  // addSceneBg()

  // camera.position.set( 5, 5, 5 );
  camera.position.set( 0, 6.5, 0 );
  camera.lookAt(0, 0, 0)
  // const glitchPass = new GlitchPass();
  // composer.addPass( glitchPass );

  // const outputPass = new OutputPass();
  // composer.addPass( outputPass );

  addPlane()

  animate();
}

// scene添加动态背景
const addSceneBg = () => {
  const vertices = [];

  for ( let i = 0; i < 5000; i ++ ) {
    const x = THREE.MathUtils.randFloatSpread( 1000 );
    const y = THREE.MathUtils.randFloatSpread( 1000 );
    const z = THREE.MathUtils.randFloatSpread( 1000 );
    vertices.push( x, y, z );
  }

  const particlesGeometry = new THREE.BufferGeometry();
  particlesGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );

  // 设置点材质
  const pointsMaterial = new THREE.PointsMaterial();
  // pointsMaterial.size = 0.9;
  pointsMaterial.color.set(new THREE.Color("#fff"));
  // 相机深度而衰减
  pointsMaterial.sizeAttenuation = true;

  const points = new THREE.Points(particlesGeometry, pointsMaterial);

  scene.add(points);

  // const texture = new THREE.TextureLoader().load( "textures/bg.jpg" );
  // // const geometry = new THREE.SphereGeometry( 1, 32, 16 );
  // const geometry = new THREE.CircleGeometry( 6, 32 );
  // const material = new THREE.MeshBasicMaterial({
  //   map: texture
  // });
  // const sphere = new THREE.Mesh( geometry, material );
  // sphere.name = "场景背景"
  // sphere.position.set(0, 0, 0)
  // sphere.rotateX(-90 * (Math.PI / 180)) // 弧度
  // scene.add( sphere );

  // texture.wrapS = THREE.RepeatWrapping;
  // texture.wrapT = THREE.RepeatWrapping;
  // scene.background = texture
}

// scene中添加plane几何体
const addPlane = () => {
  const geometry = new THREE.PlaneGeometry( 20, 20);
  const material = new THREE.MeshBasicMaterial( {
    color: new THREE.Color("gray"), 
    side: THREE.FrontSide, 
    alphaHash: true,
    // alphaTest: 0,
    opacity: 0
  } );
  const plane = new THREE.Mesh( geometry, material );
  plane.rotateX(-90 * (Math.PI / 180)) // 弧度
  plane.name = "地面"
  scene.add( plane );
}

// 用requestAnimationFrame进行渲染循环
// let bgMesh = scene.getObjectByName("场景背景")
// console.log(123, bgMesh)
const animate = () => {
  requestAnimationFrame( animate );
  TWEEN.update()
  // let bgMesh = scene.getObjectByName("场景背景")
  // if (bgMesh) {
  //   bgMesh.rotation.z += 0.0002
  // }
  // renderer.render( scene, camera );
  composer.render()
}

// 场景跟随浏览器窗口大小自适应
const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

// 初始化游戏
const initGame = async () => {
  // 初始化玩家
  initPlayer()
  // 初始化场地
  initSite()
  // 初始化卡组
  await initDeck()
  // 初始化手牌
  await initHand()
  // 绑定手牌事件
  onHandEvent()
}

// 初始化玩家
const initPlayer = () => {
  playerRef.value.init()
}

// 初始化场地
const initSite = () => {
  siteRef.value.init()
}

// 初始化卡组
const initDeck = () => {
  return new Promise((resolve, reject) => {
    let p1Deck = [
      "YZ-01",
      "YZ-02",
      "YZ-03",
      "YZ-04",
      "YZ-01",
      "YZ-02",
      // "YZ-03",
      // "YZ-04",
      // "YZ-01",
      // "YZ-02",
      // "YZ-03",
      // "YZ-04",
    ]
    // 洗牌
    p1Deck.sort(() => {
      return Math.random() - 0.5
    })
    let newDeck: any = []
    p1Deck.forEach((v: any, i: any) => {
      let obj = CARD_DICT.find((b: any) => b.card_id === v)
      if (obj) {
        newDeck.push({
          card_id: v,
          name: `${obj.name}_${i}`
        })
      }
    })
    // console.log("p1Deck", newDeck)
    commonStore.updateP1Deck(newDeck)
    
    nextTick(() => {
      handRef.value.init()
      deckRef.value.init()
      resolve(true)
    })
  })
}

// 初始化手牌
const initHand = () => {
  return new Promise((resolve, reject) => {
    let cardNumber = 4
    let _number = 0
    let p1Deck = JSON.parse(JSON.stringify(commonStore.$state.p1Deck))
    let deckGroup = scene.getObjectByName("p1_deckGroup")
    let position = new THREE.Vector3(0, 0.005 * p1Deck.length, 0)
    let _interval = setInterval(async() => {
      // console.log(123, p1Deck)
      if (_number < cardNumber) {
        let obj = p1Deck[p1Deck.length - 1]
        p1Deck.splice(p1Deck.length-1, 1)
        commonStore.updateP1Deck(p1Deck)
        // 修改卡组
        await editDeckCard(deckGroup, obj, "remove")
        await renderDeckText(deckGroup, `${commonStore.$state.p1Deck.length}`, commonStore.$state._font, position)
        // 手牌区添加手牌
        handRef.value.addHandCard(obj, deckGroup)
      } else {
        clearInterval(_interval)
        resolve(true)
      }
      _number++
    }, 200)
  })

}

// 鼠标按下事件
const onMousedown = (ev: any) => {
  // console.log(222, ev.target)
  // 判断是否点击到canvas上
  if(!(ev.target instanceof HTMLCanvasElement)){
    return;
  }
  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  let clientX = ev.clientX || ev.changedTouches[0].pageX
  let clientY = ev.clientY || ev.changedTouches[0].pageY

  let point = transPos(clientX, clientY)

  // 通过摄像机和鼠标位置更新射线
  raycaster.setFromCamera( point, camera );

  // 点击卡组事件
  // onP1DeckEvent()
}

// 点击卡组事件
const onP1DeckEvent = () => {
  if (commonStore.$state.p1Deck.length <= 0) {
    return
  }
  let p1_deckGroup = scene.getObjectByName("p1_deckGroup")
  let arr = raycaster.intersectObject(p1_deckGroup, true)
  if (arr.length <= 0) {
    return
  }
  let pos1 = p1_deckGroup.userData.position
  let pos2 = new THREE.Vector3(0, 2, 0)
  // console.log(444, pos1, pos2)
  if (p1_deckGroup.position.x !== pos2.x) {
    drawCardRef.value.drawCardAnimate1(p1_deckGroup, pos1, pos2)
  }
}

// 鼠标移动事件
const onMousemove = (ev: any) => {
  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  pointer.x = ev.clientX || ev.changedTouches[0].pageX
  pointer.y = ev.clientY || ev.changedTouches[0].pageY
}

// 手牌事件
const onHandEvent = () => {
  let handGroup = scene.getObjectByName("p1_handGroup")
  const dragControls = new DragControls( handGroup.children, camera, renderer.domElement );

  dragControls.addEventListener( 'dragstart', function ( event: any ) {
    event.object.position.y += 0.04
  });

  dragControls.addEventListener( 'drag', function ( event: any ) {
    event.object.position.y += 0.04
    
  });

  dragControls.addEventListener( 'dragend', function ( event: any ) {
    event.object.position.y -= 0.04
    let p1SitePlane = scene.getObjectByName("己方战域Plane")
    let point = transPos(pointer.x, pointer.y)
    // 通过摄像机和鼠标位置更新射线
    raycaster.setFromCamera( point, camera );
    const intersects = raycaster.intersectObjects(p1SitePlane.children);
    if (intersects.length > 0) {
      dialogRef.value.init({
        type: "handToSite",
        obj: event.object,
        message: "是否上场该卡牌"
      })
    } else {
      handRef.value.backPosition(event.object)
    }
  });
}

// 手牌移入己方战域
const handToSite = (data: any) => {
  let sitePlane = scene.getObjectByName("己方战域Plane")
  console.log(data)
  let userData = data.userData
  if (userData.type === "怪兽") {
    let meshes = sitePlane.children.filter((v: any) => v.name.indexOf("己方怪兽区") > -1 && v.userData.empty === true)
    if (meshes.length > 0) {
      let _mesh = null
      let m1 = meshes.find((v: any) => v.name.indexOf(1) > -1)
      let m2 = meshes.find((v: any) => v.name.indexOf(2) > -1)
      let m3 = meshes.find((v: any) => v.name.indexOf(3) > -1)
      if (m2) {
        _mesh = m2
      } else if (m1) {
        _mesh = m1
      } else if (m3) {
        _mesh = m3
      }
      renderSiteCard(data, _mesh)
    }
  }
}

// 绘制场上卡牌
const renderSiteCard = async (data: any, mesh: any) => {
  let p1_handGroup = scene.getObjectByName("p1_handGroup")
  let position = new THREE.Vector3(0, 0, 0)
  mesh.getWorldPosition(position)
  mesh.userData.empty = false
  let oldMesh = p1_handGroup.children.find((v: any) => v.name === data.name)
  let newMesh = oldMesh.clone()
  newMesh.userData.areaType = mesh.name // 用来记录卡牌在哪个区域,怪兽区、墓地、手牌、卡组、场地等
  newMesh.scale.set(0.8, 0.8, 0.8)
  handRef.value.removeHandCard(oldMesh)
  scene.add(newMesh)
  newMesh.position.set(position.x, position.y, position.z)
  await renderSiteCardText(newMesh, commonStore.$state._font)

  // 创建伽马校正通道
  // const gammaPass= new ShaderPass(GammaCorrectionShader)
  // composer.addPass( gammaPass );
  
  // const outlinePass = new OutlinePass(new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera); // 模糊
  // outlinePass.edgeStrength = 1.0; // 调整边缘强度
  // outlinePass.edgeGlow = 1.0; // 边缘发光强度
  // outlinePass.usePatternTexture = false; // 是否使用纹理
  // outlinePass.visibleEdgeColor.set(0xffffff); // 设置边缘颜色
  // outlinePass.hiddenEdgeColor.set(0x000000); // 设置隐藏边缘的颜色

  // outlinePass.selectedObjects = [newMesh.children[0]]
  // composer.addPass( outlinePass );
  console.log(123, newMesh)
}

// 取消
const onCancel = (data: any) => {
  handRef.value.backPosition(data)
}
</script>

<style lang="scss" scoped>
.scene {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
}
</style>

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

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

相关文章

【干货分享】OpenHarmony轻量系统适配方案

1. 简介 本文在不改变原有系统基础框架的基础上&#xff0c; 介绍了一种OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;轻量系统适配方案。 本方案使用的是 OpenHarmony v3.2 Release版本源码。 2. 方案设计 本文使用的硬件模块的主要特性及功能如…

基于最小二乘支持向量机(LSSVM)的数据时序预测(单输入输出)

作品描述付费内容发布设置 宋体 黑体 微软雅黑 monospace cursive Sans Serif Inconsolata Roboto Mirza Arial 代码原理 基于最小二乘支持向量机&#xff08;LSSVM&#xff09;的数据时序预测&#xff08;单输入输出&#xff09;是指利用LSSVM模型来预测未来时序数据的单个…

Flutter环境搭建及版本管理

前言 Flutter已成为移动应用开发的主流选择&#xff0c;其跨平台优势日益凸显&#xff0c;使学习Flutter成为现代开发者的必备技能。越来越多的公司和团队选择Flutter构建应用&#xff0c;这为开发者提供了更广阔的就业机会和职业发展空间。Flutter的热度源自其强大的特性和生…

某红队面试经验

背景 据小道消息说今年的国护疑似提前到了五月份&#xff0c;所以最近也是HW面试的一个高峰期啊&#xff0c;这里分享一下上次的红队面试问题 面试问答 问&#xff1a;Java 反序列化的原理&#xff1f; 答&#xff1a;如果Java应用对用户输入&#xff0c;即不可信数据做了反…

Docker命令及部署Java项目

文章目录 简介Docker镜像镜像列表查找镜像拉取镜像删除镜像镜像标签 Docker容器容器启动容器查看容器停止和重启后台模式和进入强制停止容器清理停止的容器容器错误日志容器别名及操作 Docker部署Java项目 简介 Docker是一种容器化技术&#xff0c;可以帮助开发者轻松打包应用…

大话设计模式之代理模式

代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许通过代理对象控制对另一个对象的访问。代理对象充当客户端和实际对象之间的中介&#xff0c;客户端通过代理对象间接访问实际对象&#xff0c;从而可以在访问控制、缓存、延迟加载等方面提…

yolo系列热力图,即插即用。

原地址&#xff1a;https://github.com/z1069614715/objectdetection_script/tree/master/yolo-gradcam

反应式编程(二)什么是粘包、拆包?如何解决?

目录 一、粘包、拆包介绍1.1 什么是 TCP 协议&#xff1f;1.2 什么是粘包、拆包&#xff1f;1.3 粘包、拆包的四种情况1.4 粘包、拆包的原因1&#xff09;TCP协议中的滑动窗口机制2&#xff09;传输层的 MSS 与链路层的 MTU3&#xff09;TCP协议中的 Nagle 算法4&#xff09;应…

git配置SSH 密钥

git配置SSH 密钥 1.window配置ssh1.安装ssh2.安装 Git&#xff08;安装教程参见安装Git&#xff09;并保证版本大于 1.9![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e59f4e16b83c45649f1d9d7bd6bf92c0.png)3.SSH 尽量保持最新&#xff0c;6.5之前的版本由于使用…

【文献分享】PyPlume程序:快速海洋表面传输评估的工具包

PyPlume: A toolkit for rapid ocean surface transport assessments PyPlume&#xff1a;快速海洋表面传输评估的工具包 PyPlume 是一个 Python 工具箱和管道&#xff0c;用于统一从模型和观测加载二维洋流矢量场、模拟轨迹模型以及分析和可视化粒子轨迹的过程。提供了 Ju…

python 如何安装redis

一、redis介绍 redis是一个非关系型的缓存数据库&#xff0c;因为是缓存所以redis的速度会非常快。redis主要是依靠键值对进行存储&#xff0c;类似于java的map、python的字典。redis支持许多的语言&#xff0c;如java、C、C、C#、PHP、JavaScript、Perl、python等。 二、pyt…

基于SSM的高校普法系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的高校普法系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

redis 的设计与实现(三)——对象

1. 前言&#xff1a; 在第一章节我们了解到了&#xff0c;redis底层所涉及的数据结构&#xff0c;但是这并非是离我们最近的一层&#xff0c;在此之上&#xff0c;redis实现了一层对象与我们交互。我们在本篇内容中将了解到&#xff1a; 对象对应的实现redis一些常用特性的实现…

物联网实战--入门篇之(三)嵌入式STM32

目录 一、Keil简介 二、工程结构 三、文件目录 四、STM32简介 五、编码风格 六、总结 一、Keil简介 Keil是一款常用的单片机开发工具&#xff0c;主要包含了编译、仿真、调试和开发界面(IDE)&#xff0c;后被ARM公司收购&#xff0c;与其MDK-ARM合并为MDK-ARM Keil软件包…

宝塔面板操作一个服务器域名部署多个网站

此处记录IP一样&#xff0c;端口不一样的操作方式&#xff1a; 宝塔面板操作&#xff1a; 1、创建第一个网站&#xff1a; 网站名用IP地址&#xff0c;默认80端口。 创建好后&#xff0c;直接IP访问就可以了。看到自带的默认首页 2、接下来部署第二个网站&#xff1a; 仍然是…

Spark-Scala语言实战(7)

在之前的文章中&#xff0c;我们学习了如何在IDEA中导入jars包&#xff0c;并做了一道例题&#xff0c;了解了RDD。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢…

自建机房私有云吗?

大家好&#xff0c;我是小码哥&#xff0c;之前一种有没搞清楚公有云、私有云的概念&#xff0c;今天算是弄清楚了&#xff0c;这里给大家分享一下公有云、私有云的区别&#xff0c;以及自建机房算不算私有云&#xff01; 其实私有云&#xff08;Private Cloud&#xff09;和公…

修复系统中缺失的VCRUNTIME140.dll文件DLL错误问题

在计算机编程中&#xff0c;动态链接库&#xff08;DLL&#xff09;是一种重要的组件&#xff0c;它提供了许多功能和资源供程序使用。其中&#xff0c;VCRuntime140.dll是Visual C Redistributable Packages的一部分&#xff0c;它包含了运行C应用程序所需的运行时库。本文将详…

双端队列deque和vector以及list的优缺点比较

参考:https://blog.csdn.net/TWRenHao/article/details/123483085 一、vector vector具体用法详情点这里 优点&#xff1a; 支持随机访问 CPU高速环缓存命中率很高 缺点&#xff1a; 空间不够&#xff0c;便需要增容。而增容代价很大&#xff0c;还存在一定的空间浪费。 头部…

DSVPN实验报告

一、分析要求 1. 配置R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;所有地址均配为公有IP地址。 - 在R5上&#xff0c;将接口配置为公有IP地址&#xff0c;并确保只进行了IP地址配置。 2. R1和R5之间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b;R2于R5之间…