植物明星大乱斗15
能帮到你的话,就给个赞吧 😘
文章目录
- player.h
- player.cpp
- particle.h
- particle.cpp
player.h
#pragma once
#include <graphics.h>
#include "vector2.h"
#include "animation.h"
#include "playerID.h"
#include "platform.h"
#include "bullet.h"
#include "particle.h"extern bool isDebug;extern Atlas atlasRunEffect;
extern Atlas atlasJumpEffect;
extern Atlas atlasLandEffect;extern std::vector<Bullet*> bullets;
extern std::vector<Platform> platforms;class Player {
public:Player();
public:virtual void receiveInput(const ExMessage& msg);virtual void update(int time);virtual void render();void setId(const PlayerID& id);void setPosition(float x, float y);
public:const Vector2& getPosition() const;const Vector2& getSize() const;
public:
//攻击virtual void onAttack() = 0;virtual void onAttackEx() = 0;
protected://无敌void makeInvulnerable();public:const int getHp() const;const int getMp() const;protected:virtual void onRun(float distance); //奔跑virtual void onJump(); //跳跃virtual void onLand(); //落地void moveAndCollide(int time); //重力和碰撞protected:const float runVelocity = 0.55; //奔跑速度const float jumpVelocity = -0.85; //跳跃速度const float gravity = 1.6e-3f; //重力加速度Vector2 velocity; //玩家速度PlayerID id = P1;//HP MPint hp = 100, mp = 0;//攻击bool isCanAttck = true;Timer timerAttckCd;int attackCd = 500;bool isAttackingEx = false;//无敌IMAGE imgSketch;bool isInvulnerable = false;bool isShowSketchFram = false; //当前帧是否应该显示剪影Timer timerInvulnerable; //玩家无敌Timer timerInvulnerableBlink; //闪烁切换//粒子特效std::vector<Particle> particles;Timer timerRunEffectGeneration; //玩家跑动粒子发射器Timer timerDieEffectGeneration; //玩家死亡粒子发射器//按键信息bool isLeftKeyDown = false;bool isRightKeyDown = false;//移动信息Vector2 position; //玩家位置Vector2 size; //碰撞尺寸bool isFacingRight = true; //玩家朝向——(根据按键决定)//渲染数据Animation animationIdleLeft;Animation animationIdleRight;Animation animationRunLeft;Animation animationRunRight;Animation animationAttackExLeft;Animation animationAttackExRight;Animation animationJumpEffect; //跳跃动画Animation animationLandEffect; //落地bool isJumpEffectVisible = false; //跳跃可见bool isLandEffectVisible = false; //落地可见Vector2 positionJumpEffect;Vector2 positionLandEffect;Animation* currentAni = nullptr;};
player.cpp
#include "player.h"Player::Player() {currentAni = &animationIdleRight;timerAttckCd.setCallback([&] {isCanAttck = true;});timerAttckCd.setTimer(attackCd);timerAttckCd.setIsOneShot(true);//无敌定时器timerInvulnerable.setCallback([&] {isInvulnerable = false;});timerInvulnerable.setTimer(750);timerInvulnerable.setIsOneShot(true);//无敌动画切换timerInvulnerableBlink.setCallback([&] {isShowSketchFram = !isShowSketchFram;});timerInvulnerableBlink.setTimer(75);//粒子发射timerRunEffectGeneration.setTimer(75);timerRunEffectGeneration.setCallback([&] {Vector2 particlePosition;auto frame = atlasRunEffect.getImage(0);//粒子位于玩家水平中央particlePosition.x = position.x + (size.x - frame->getwidth()) / 2;//玩家脚底particlePosition.y = position.y + size.y - frame->getheight();particles.emplace_back(particlePosition, &atlasRunEffect, 45);});timerDieEffectGeneration.setTimer(35);timerDieEffectGeneration.setCallback([&] {Vector2 particlePosition;auto frame = atlasRunEffect.getImage(0);//粒子位于玩家水平中央particlePosition.x = position.x + (size.x - frame->getwidth()) / 2;//玩家脚底particlePosition.y = position.y + size.y - frame->getheight();particles.emplace_back(particlePosition, &atlasRunEffect, 150);});//跳跃和落地animationJumpEffect.setAtlas(&atlasJumpEffect);animationJumpEffect.setInterval(25);animationJumpEffect.setIsLoop(false);animationJumpEffect.setCallback([&] {isJumpEffectVisible = false;});animationLandEffect.setAtlas(&atlasLandEffect);animationLandEffect.setInterval(50);animationLandEffect.setIsLoop(false);animationLandEffect.setCallback([&] {isLandEffectVisible = false;});}void Player::setId(const PlayerID& id){this->id = id;
}void Player::setPosition(float x, float y){position.x = x, position.y = y;
}const Vector2& Player::getPosition() const{return position;
}const Vector2& Player::getSize() const{return size;
}void Player::makeInvulnerable(){isInvulnerable = true;timerInvulnerable.reStart();
}const int Player::getHp() const{return hp;
}const int Player::getMp() const{return mp;
}void Player::onRun(float distance){if (isAttackingEx)return;position.x += distance;timerRunEffectGeneration.resume();
}void Player::onJump(){if (velocity.y || isAttackingEx)return;//仅需更改速度即可//位置在moveAndCollide修改velocity.y += jumpVelocity;//跳跃isJumpEffectVisible = true;animationJumpEffect.reset();auto frame = animationJumpEffect.getFrame();//jump位于玩家中央positionJumpEffect.x = position.x + (size.x - frame->getwidth()) / 2;positionJumpEffect.y = position.y + size.x - frame->getheight();}void Player::onLand(){//落地isLandEffectVisible = true;animationLandEffect.reset();auto frame = animationLandEffect.getFrame();//jump位于玩家中央positionLandEffect.x = position.x + (size.x - frame->getwidth()) / 2;positionLandEffect.y = position.y + size.x - frame->getheight();
}void Player::moveAndCollide(int time){auto lastVelocityY = velocity.y;velocity.y += gravity * time;position += velocity * time;//碰撞检测//玩家与平台if (velocity.y) {for (const auto& platform : platforms) {const auto& shape = platform.shape;bool isCollideX = max(position.x + size.x, shape.right) - min(position.x, shape.left) <= shape.right - shape.left + size.x;bool isCollideY = shape.y >= position.y && shape.y <= position.y + size.y;//对玩家坐标进行修正if (isCollideX && isCollideY) {//判断上一帧玩家是否在平台之上auto deltaY = velocity.y * time;auto lastY = position.y + size.y - deltaY;if (lastY <= shape.y) {position.y = shape.y - size.y;//平台上速度为0velocity.y = 0;if (lastVelocityY)onLand();break;}}}}//玩家与子弹if (!isInvulnerable) {for (const auto& bullet : bullets) {if (!bullet->getValid() || bullet->getCollideTarget() != id)continue;if (bullet->checkCollision(position, size)) {makeInvulnerable();bullet->onCollide();bullet->setValid(false);hp -= bullet->getDamage();}}}}void Player::receiveInput(const ExMessage& msg){switch (msg.message){case WM_KEYDOWN:switch (id){case P1:switch (msg.vkcode){//'A'case 0x41:isLeftKeyDown = true;break;//'D'case 0x44:isRightKeyDown = true;break;//'W'case 0x57:onJump();break;//'J'case 0x4a:if (isCanAttck) {onAttack();isCanAttck = !isCanAttck;timerAttckCd.reStart(); }break;//'K'case 0x4b:if (mp >= 100) {onAttackEx();mp = 0;}break;default:break;}break;case P2:switch (msg.vkcode) {//<case VK_LEFT:isLeftKeyDown = true;break;//>case VK_RIGHT:isRightKeyDown = true;break;//'↑'case VK_UP:onJump();break;//'1'case 0x6e:if (isCanAttck) {onAttack();isCanAttck = !isCanAttck;timerAttckCd.reStart();}break;//'2'case 0x62:if (mp >= 100) {onAttackEx();mp = 0;}break;default:break;}break;default:break;}break;case WM_KEYUP:switch (id) {case P1:switch (msg.vkcode) {//'A'case 0x41:isLeftKeyDown = false;break;//'D'case 0x44:isRightKeyDown = false;break;default:break;}break;case P2:switch (msg.vkcode) {//<case VK_LEFT:isLeftKeyDown = false;break;//>case VK_RIGHT:isRightKeyDown = false;break;default:break;}break;default:break;}break;default:break;}}void Player::update(int time){//direction:——玩家是否按键: 0——没有按键int direction = isRightKeyDown - isLeftKeyDown;//按键if (direction) {//特殊攻击时不允许转向if(!isAttackingEx)isFacingRight = direction > 0; //根据按键判断当前朝向//根据当前朝向 选择 动画currentAni = isFacingRight ? &animationRunRight : &animationRunLeft;//水平方向移动auto distance = direction * runVelocity * time;onRun(distance);}else {currentAni = isFacingRight ? &animationIdleRight : &animationIdleLeft;timerRunEffectGeneration.pause();}if (isAttackingEx)currentAni = isFacingRight ? &animationAttackExRight : &animationAttackExLeft;//更新动画currentAni->update(time);animationJumpEffect.update(time);animationLandEffect.update(time);//更新定时器timerAttckCd.update(time);timerInvulnerable.update(time);timerInvulnerableBlink.update(time);//粒子//生成粒子timerRunEffectGeneration.update(time);if (hp <= 0)timerDieEffectGeneration.update(time);//更新粒子particles.erase(std::remove_if(particles.begin(), particles.end(), [](const Particle& particle) {return !particle.checkIsValid();}), particles.end());for (auto& particle : particles)particle.update(time);//剪影if (isShowSketchFram)sketchImage(currentAni->getFrame(), &imgSketch);//重力模拟 和 碰撞检测moveAndCollide(time);
}void Player::render(){if (isJumpEffectVisible)animationJumpEffect.render(positionJumpEffect.x, positionJumpEffect.y);if (isLandEffectVisible)animationLandEffect.render(positionLandEffect.x, positionLandEffect.y);//让粒子渲染在玩家身后for (const Particle& particle : particles)particle.render();if (hp > 0 && isInvulnerable && isShowSketchFram)putImageAlpha(position.x, position.y, &imgSketch);elsecurrentAni->render(position.x, position.y);if (isDebug) {setlinecolor(RGB(0, 125, 255));rectangle(position.x, position.y, position.x + size.x, position.y + size.y);}
}
particle.h
#pragma once#include "atlas.h"
#include "vector2.h"
#include "util.h"class Particle {public:Particle() = default;Particle(const Vector2& position, Atlas* atlas, int lifeSpan) :position(position), lifeSpan(lifeSpan),atlas(atlas) {}public:
//设置void setPosition(const Vector2& position);void setAtlas(Atlas* atlas);void setLifeSpan(int lifeSpan);//检测bool checkIsValid() const;//更新void update(int deltaT);
//渲染void render() const;private://物理Vector2 position;bool isValid = true; //粒子是否有效//渲染int timer = 0; //计时器int lifeSpan = 0; //单帧持续时间int index = 0; //当前帧Atlas* atlas = nullptr;
};
particle.cpp
#include "particle.h"void Particle::setPosition(const Vector2& position){this->position = position;
}void Particle::setAtlas(Atlas* atlas){this->atlas = atlas;
}void Particle::setLifeSpan(int lifeSpan){this->lifeSpan = lifeSpan;
}bool Particle::checkIsValid() const{return isValid;
}void Particle::update(int deltaT){timer += deltaT;if (timer >= lifeSpan) {timer = 0;index++;//粒子在播完动画后消失if (index == atlas->getSize()) {index = atlas->getSize() - 1;isValid = false;}}
}void Particle::render() const{putImageAlpha(position.x, position.y, atlas->getImage(index));
}相关文章:
植物明星大乱斗15
能帮到你的话,就给个赞吧 😘 文章目录 player.hplayer.cppparticle.hparticle.cpp player.h #pragma once #include <graphics.h> #include "vector2.h" #include "animation.h" #include "playerID.h" #include &…...
go-zero(三) 数据库操作
go-zero 数据库操作 在本篇文章中,我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API,包括请求参数和响应参数的定义。 一、Mysql连接 1. 创建数据库和表 在 MySQL 中创建名为 test_zero的数据库,并创建user 表 …...
SQL面试题——间隔连续问题
间隔连续问题 某游戏公司记录的用户每日登录数据如下 +----+----------+ | id| date| +----+----------+ |1001|2021-12-12| |1001|2021-12-13| |1001|2021-12-14| |1001|2021-12-16| |1001|2021-12-19| |1001|2021-12-20| |1002|2021-12-12| |1002|2021-12-16| |1002|…...
vim配置 --> 在创建的普通用户下
在目录/etc/ 下面,有个名为vimrc 的文件,这是系统中公共的vim配置文件对所有用户都有效 我们现在创建一个普通用户 dm 创建好以后,我们退出重新链接 再切换到普通用户下 再输入密码(是不显示的,输入完后,…...
(计算机毕设)基于SpringBoot+Vue的房屋租赁系统的设计与实现
博主可接毕设设计!!! 各种毕业设计源码只要是你有的题目我这里都有源码 摘 要 社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。互…...
【含开题报告+文档+PPT+源码】基于SpringBoot的医院药房管理系统
开题报告 在科技迅速发展的今天,各行各业都在积极寻求与现代技术的融合,以提升自身的运营效率和竞争力。医疗行业作为关乎国计民生的关键领域,其信息化建设的步伐尤为迅速。医院药房作为医疗体系中的核心环节,其管理效率和服务质…...
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 数码板…...
Linux-第2集-打包压缩 zip、tar WindowsLinux互传
欢迎来到Linux第2集,这一集我会非常详细的说明如何在Linux上进行打包压缩操作,以及解压解包 还有最最重要的压缩包的网络传输 毕竟打包压缩不是目的,把文件最终传到指定位置才是目的 由于打包压缩分开讲没有意义,并且它们俩本来…...
项目进度计划表:详细的甘特图的制作步骤
甘特图(Gantt chart),又称为横道图、条状图(Bar chart),是一种用于管理时间和任务活动的工具。 甘特图由亨利劳伦斯甘特(Henry Laurence Gantt)发明,是一种通过条状图来…...
Cargo Rust 的包管理器
Cargo->Rust 的包管理器 Cargi简介Cargo 的主要功能1. 创建项目2. 管理依赖3. 构建项目4. 运行项目5. 测试代码6. 检查代码7. 生成文档8. 发布和分享包 Cargo 的核心文件1. Cargo.toml2. Cargo.lock **Cargo 的生态系统** 常用命令总结Hello, Cargo! 示例 Cargi简介 Cargo …...
【Rust 编程语言工具】rustup-init.exe 安装与使用指南
rustup-init.exe 是用于安装和管理 Rust 编程语言工具链的 Windows 可执行文件。Rust 是一种系统级编程语言,旨在提供安全、并发和高性能的功能。rustup-init.exe 是官方提供的安装器,用于将 Rust 安装到 Windows 操作系统中,并配置相关环境。…...
集群聊天服务器(12)nginx负载均衡器
目录 负载均衡器nginx负载均衡器优势 如何解决集群聊天服务器跨服务器通信问题?nginx的TCP负载均衡配置nginx配置 负载均衡器 目前最多只能支持2w台客户机进行同时聊天 所以要引入集群,多服务器。 但是客户连哪一台服务器呢?客户并不知道哪一…...
数据挖掘英语及概念
分类 classify 上涨或跌 回归 regression 描述具体数值 分类模型评估 1.混淆(误差)矩阵 confusion matrix 2.ROC曲线 receiver operating characteristic curve 接收者操作特征曲线 3.AUC面积 area under curve ROC曲线下与坐标轴围成的面积&#x…...
springboot第82集:消息队列kafka,kafka-map
官网下载链接:https://kafka.[apache].org/downloads 我下载的是[Scala]2.12 - kafka_2.12-3.1.0.tgz kafka只需要解压下载的压缩包就行了,我这里解压的路径是D:\kafka_2.12-3.1.0,kafka的运行需要依赖zookeeper,当前版本已经内置…...
sql server查看当前正在执行的sql
#统计某类sql执行次数,并按总体cpu消耗时间降序排序 with a as ( select er.session_id,db_name(er.database_id) as DBNAME,sy.last_batch AS 最后执行时间, er.cpu_time ,er.total_elapsed_time/1000 as sum_elapsed_time_s, CAST(csql.text AS varchar(8000)) A…...
STM32设计学生宿舍监测控制系统-分享
目录 前言 一、本设计主要实现哪些很“开门”功能? 二、电路设计原理图 电路图采用Altium Designer进行设计: 三、实物设计图 四、程序源代码设计 五、获取资料内容 前言 本项目旨在利用STM32单片机为核心,结合传感器技术、无线通信技…...
HAproxy 详解
一、基本概念 1.1 什么是 HAproxy? HAproxy(High Availability Proxy)是一个开源的高性能负载均衡器和反向代理服务器,它主要用于在网络上分发流量,以提高网站或应用程序的可用性和性能。HAproxy 可以处理大量的并发…...
间接采购管理:主要挑战与实战策略
间接采购支出会悄然消耗掉企业的现金流,即使是管理完善的公司也难以避免。这是因为间接支出不直接关联特定客户、产品或项目,使采购人员难以跟踪。但正确管理间接支出能为企业带来显著收益——前提是要有合适的工具。本文将分享管理间接支出的关键信息与…...
2411rust,正与整128
原文 长期以来,Rust在x86-32和x86-64架构上128位整数的对齐与C语言不一致.最近已解决此问题,但该修复带来了一些值得注意的效果. 作为用户,除非如下,否则不用担心: 1,假设i128/u128对齐,而不是用align_of 2,忽略improper_ctypes*检查,并在FFI中使用这些类. 除x86-32和x86-64…...
将 HTML 转换为 JSX:JSX 和 JSX 规则
JSX 是 JavaScript 的语法扩展。您可以在 JavaScript 文件中编写 HTML 格式。 它基于 Web、Html、Css 和 JavaScript。Web 开发人员将页面内容分别编写为 Html 文件,将设计编写为 Css 文件,将逻辑编写为 JavaScript 文件。 须知 : JSX 是一个…...
开源情报自动化工具OpenClaw:模块化设计与实战部署指南
1. 项目概述:从“Resolver-TNG/ogas-openclaw”看开源情报自动化最近在开源情报(OSINT)和自动化数据采集的圈子里,一个名为“ogas-openclaw”的项目引起了我的注意。这个项目托管在Resolver-TNG的组织下,名字本身就很有…...
基于图特征选择与XGBoost的电动公交预测性维护模型构建
1. 项目概述:从数据洪流到精准预警的挑战在电动公交的日常运营中,车辆控制器局域网(CAN)总线每秒都在产生海量的传感器数据,从电池电压、电机温度到刹车片厚度,这些数据流如同车辆的“生命体征”。预测性维…...
渗透PHP伪协议
一、debug调试 1、定义 Debug,又叫断点调试,就是对写好的程序进行逐步运行、分解、调试的过程,通过这个过程,我们可以跟踪程序的详细运行过程, 是程序员的开发神器,也是开发必会的一个重要技能。 2、意义…...
从‘咖啡环’到‘热点’富集:超疏水表面如何将SERS检测灵敏度提升几个数量级?
从“咖啡环效应”到分子富集革命:超疏水表面如何重塑痕量检测极限 清晨的咖啡杯边缘总留下一圈深色痕迹,这个看似普通的日常现象背后,隐藏着改变分子检测游戏规则的物理机制。当科研人员将这种被称为"咖啡环效应"的液滴蒸发现象与表…...
从找石油到防灾害:地震勘探技术如何跨界守护城市安全?
地震勘探技术的跨界革命:从油气勘探到城市安全守护者 上世纪20年代,当第一批地球物理学家尝试用炸药激发地震波来寻找石油时,他们或许不会想到,这项技术会在百年后成为保护现代城市安全的"透视眼"。传统的地震勘探技术…...
告别CubeMX代码洁癖:教你如何把main()函数挪到自己的.c文件里(STM32F4实战)
重构STM32工程的艺术:将main()迁移到自定义文件的实战指南 每次打开CubeMX生成的工程,看到那个被各种初始化代码塞满的main.c文件,你是否也感到一丝不适?作为一名有追求的嵌入式开发者,我们渴望对项目结构拥有绝对掌控…...
FastAPI项目实战:从零构建现代化Python Web API的完整指南
1. 从零到一:一个完整的 FastAPI 项目实战复盘最近在社区里看到一个挺有意思的葡萄牙语开源教程项目,叫“FastAPI do Zero”。虽然页面是葡萄牙语,但技术栈和路径对我们来说再熟悉不过了:FastAPI、Pydantic、SQLAlchemy、Alembic&…...
基于宏观通胀预测模型的利率预期重定价:华尔街降息路径为何出现系统性回撤?CPI成为关键校准变量
摘要:本文通过宏观通胀预测模型,结合利率预期曲线重定价算法与市场情绪迁移分析,对当前美通胀路径、CPI数据影响及华尔街降息预期变化进行系统性建模,分析利率政策预期从宽松交易向数据依赖模式切换的结构性原因。一、市场情绪迁移…...
动态架构跳跃:让视觉语言大模型高效适配垂直领域任务
1. 项目概述:从“大而全”到“快而准”的模型进化之路 在视觉语言预训练模型(Vision-Language Pre-trained Models, VLPMs)如CLIP、ALIGN等席卷多模态领域的今天,一个核心的工程与学术困境日益凸显:这些动辄数十亿参数…...
图像理解的底层逻辑:从像素到语义的三层跃迁
1. 这不是“看图说话”,而是让机器学会“看见”的底层逻辑 你有没有想过,当手机相册自动给你把“猫”和“狗”的照片分到不同相册里,或者修图App能一键抠出人像边缘、连发丝都清晰分明,背后到底发生了什么?很多人以为A…...
