面向对象02 - 案例:王者荣耀英雄选择
王者荣耀英雄选择案例
- 一、目标与说明
- 二、实现效果
- 三、写之前先分析
- 四、类
- 1. 玩家类
- 2. 亚瑟类
- 3. 鲁班类
- 4.英雄基类
- 5. 技能类和皮肤类
- 6. 总结
- 五、页面结构和逻辑
- 1. 页面元素
- 2. Style样式
- 3. 逻辑操作
- 六、 总结
一、目标与说明
- 还是注重逻辑分析,图片素材为游戏截屏抠图而成,不涉及王者炫酷的动画效果。
- 运用面向对象的思想,在这里我会分析王者荣耀运用了哪些对象,然后抽离里面的功能和方法、抽离成类、研究每个类之间的逻辑关系、把每个类模块化。
- 最终实现进入登录界面完成登陆、选择英雄、选择皮肤、释放技能等一系列功能。
- 为什么要用面向对象来做?王者荣耀上百个英雄,每个英雄又对应各自的皮肤和技能。按照面向对象思想,根据项目的特点,把类与类之间的逻辑关系写好,实现模块化功能,到时候上百个英雄只需要直接对类进行实例化就可以完成功能,代码更加易于管理和高效。
- 实现功能并不难,怎么划分对象、怎么划分功能、搞清楚对象与对象之间的关系是关键点。
二、实现效果
王者荣耀英雄选择案例效果图
三、写之前先分析
- 写之前先分析一波:假设我已经知道面向对象的思想、知道什么是对象、类、原型、继承等,现在有了这样一个需求,我该怎么把思维从面向过程转变为面向对象呢?
- 可以按照以下步骤:
- 根据需求研究对象,比如我今天就写两个英雄,不需要研究一大堆东西,一切从需求出发就行。要考虑有哪些对象?对象有哪些属性和方法?有什么特性?
- 抽象成类,提升复用性。如果是一个类,它就不止一个对象,可能有成百上千个对象,抽离这些对象中的一些共性的东西成类。如果某个对象有特殊的功能的话,就没必要抽离成类。
- 上一步研究完对象的共性,已经抽离成类了,这一步可以根据需求研究类的共性问题,即抽离类成为基类(父类),这时候就可以考虑继承的问题。但是是根据需求来,如果需求简单,就没必要这么做。
- 研究类之间的逻辑关系,研究这个类需要那个类,这个类调用那个类等等。
- 在王者荣耀这个案例中,我列出来的对象有:亚瑟、鲁班、玩家、技能、皮肤、游戏管理类game
- 文件目录如下图:
四、类
1. 玩家类
import Yase from './yase.js';
import Luban from './luban/js'
export default class Player{constructor(username){this.name = username;this.heroes = [new Yase,new Luban];}
}
- 玩家就是用户,在这个案例中只涉及到了用户名和玩家拥有的英雄,所以只有两个属性name和heroes
- 真正的游戏还有很多属性,例如等级啊、积分啊、钻石啊、点券等等
- 这个界面引入了两个类,亚瑟类和鲁班类,是属于玩家的英雄,这里就可以显现面向对象的好处了,如果玩家还有其他英雄如李白,只需要引入李白类,并在heroes里面进行实例化即可。
2. 亚瑟类
//亚瑟类
import Hero from './hero.js'import S1 from './skills/yase/s1.js'
import S2 from './skills/yase/s2.js'
import S3 from './skills/yase/s3.js'import Skin1 from './skins/yase/skin1.js';
import Skin2 from './skins/yase/skin2.js';
import Skin3 from './skins/yase/skin3.js';export default class Yase extends Hero{constructor(){let opts = {name: "亚瑟",ico: "./sources/heros/yase1.png",skills: [new S1(),new S2,new S3],skins: [new Skin1,new Skin2,new Skin3]}super(opts);// this.name = "亚瑟";// this.ico = "./sources/heros/yase1.png";// this.skills = [new S1(),new S2,new S3];// this.skins = [new Skin1,new Skin2,new Skin3];}
}
- 亚瑟类包含四个属性,分别是英雄名、英雄图标、技能和皮肤
- 技能被抽离成类,引入了三个技能S1,S2,S3,并实例化
- 皮肤也被抽离成类,引入了三个皮肤Skin1,Skin2,Skin3,并实例化
- 因为亚瑟、鲁班都是英雄,我在这里将亚瑟类和鲁班类的共性抽离成基类,即英雄类,所以这里引入了Hero类
- 在这个案例中其实没必要抽离基类,下面注释是没有抽离的写法,是否抽离应该按实际需求来
3. 鲁班类
//鲁班类
import Hero from './hero.js'import S1 from './skills/luban/s1.js'
import S2 from './skills/luban/s2.js'
import S3 from './skills/luban/s3.js'import Skin1 from './skins/luban/skin1.js'
import Skin2 from './skins/luban/skin2.js'
import Skin3 from './skins/luban/skin3.js'export default class Luban extends Hero{constructor(){let opts = {name : "鲁班",ico : "./sources/heros/luban1.png",skills : [new S1(),new S2(),new S3()],skins : [new Skin1,new Skin2, new Skin3],}super(opts);}
}
- 说明和亚瑟类相似,这里不赘述
4.英雄基类
// 英雄基类;
import GameEvent from './GameEvent.js';
export default class Hero extends GameEvent{constructor({name,ico,skills,skins}){super();this.name = name;this.ico = ico;this.skills = skills;this.skins = skins;// 绑定自定义事件this.addEvent("myinit",this.init);}init(){console.log("初始化了");}
}
- 抽离出一些英雄的共性,例如name、ico、skills、skins
- 进行了一个初始化实现(功能很简单哈哈哈,只打印了一下初始化了)
- 这里的addEvent方法是继承的父类GameEvent里面的添加事件的方法
- 父类GameEvent就是用来管理一些事件的添加移除的,这里不过多赘述,详细代码可以下载源码查看
5. 技能类和皮肤类
- 逻辑比较简单我就以图片形式呈现啦
- 技能类包含了两个属性 name 和 ico,以及一个释放技能 release 方法
- 皮肤类就简简单单包含了三个属性 name 、ico、 img;注意,ico是小图标;img是大图片
6. 总结
- 类与类之间的关系就说到这里啦,看似抽离了这么多类很麻烦,但其实一旦英雄数量多起来,玩家多起来,就会显现出这样做的好处,逻辑更清晰、更易于管理,哪里出现了bug也可以第一时间发现
- 所以大家还是慢慢学会转变自己的思想,从面向过程到面向对象
五、页面结构和逻辑
1. 页面元素
<body><!-- 登录页面 --><div class="login"><input class="username" /> <button class="sub">登录</button><img src="./sources/login.JPG" alt=""></div><!-- 游戏选择页面 --><div class="game"><button class="heroBtn">英雄</button><div class="heroContainer"><div class="heroView"><div class="heroItem"><img src="./sources/heros/yase1.png" /><span>亚瑟</span></div><div class="heroItem"><img src="./sources/heros/yase1.png" /><span>亚瑟</span></div></div></div><button class="skinBtn">皮肤</button><div class="skinContainer"><div class="skinView"><!-- <div class="skinItem"><img src="./sources/heros/yase1.png" /><span>经典</span></div><div class="skinItem"><img src="./sources/heros/yase2.png" /><span>死亡骑士</span></div> --></div></div><div class="skinShow"><img src="./sources/skins/301660.png" alt=""></div><div class="userView"><div class="heroShow"><!-- <img src="./sources/heros/yase1.png" /> --></div><span class="chioseusername">张三</span></div><div class="skillsView"><!-- <img src="./sources/skills/11210.png" /><img src="./sources/skills/11220.png" /><img src="./sources/skills/11230.png" /> --></div><div></div><img src="./sources/chiose.JPG" /></div><script type="module" src="./index.js"></script>
</body>
- 主要是一些 div 结构,注意 class 类名要起的很规范,这样写逻辑操作DOM结构的时候才不会乱套
- 代码倒数第二行采用模块化思想,导入 index.js 业务逻辑
2. Style样式
<style>body {margin: 0;padding: 0;}.username {position: absolute;left: 347px;top: 250px;border-radius: 5px;height: 24px;}button {background: transparent;outline: none;border: none;color: white;}.heroShow{width: 50px;height: 50px;}.sub {position: absolute;left: 351px;top: 288px;width: 126px;color: white;font-weight: bold;font-size: 18px;}.geme {position: relative;}.heroBtn {position: absolute;left: 45px;top: 8px;font-size: 14px;}.skinBtn {position: absolute;top: 8px;left: 105px;font-size: 14px;}.userView{position: absolute;/* width: 80px; */top: 34px;left: 720px;}.userView img{width: 40px;height: 40px;}.chioseusername {display: block;color: rgb(255, 215, 0);text-align: center;font-size: 12px;font-weight: bold;}.skillsView {position: absolute;display: flex;flex-direction: column;left: 660px;top: 200px;}.skillsView img {width: 40px;height: 40px;margin-bottom: 10px;}.heroView{width: 120px;position:absolute;margin-top: 40px;margin-left: 20px;display: flex;flex-wrap: wrap;}.skinView{width: 130px;position:absolute;margin-top: 40px;margin-left: 20px;display: flex;flex-wrap: wrap;}.heroView img {width: 50px;height: 50px;}.skinView img{width: 50px;height: 50px;}.heroItem{margin-left: 10px;margin-top: 10px;display: flex;flex-direction: column;color: gray;align-items: center;font-size: 12px;}.skinItem{margin-left: 10px;margin-top: 10px;display: flex;flex-direction: column;color: gray;align-items: center;font-size: 12px;}.skinShow{position:absolute;left:320px;top: 40px;}.login {display: block;}.game{display: none;}.heroContainer{display: block;}.skinContainer{display: none;}</style>
- 我这里直接写进 style 标签里了,其实更好的做法应该是写css文件,然后引入进来
3. 逻辑操作
import Game from './game/game.js';// 对象: 鲁班、亚瑟、玩家、技能、游戏管理类;let game = new Game();function decorator(fn1,fn2,skill,...arg){fn1.call(skill);fn2(...arg);
}function hurt(num){console.log("造成"+num+"点伤害");
}document.querySelector(".sub").onclick = function(){let username = document.querySelector(".username").value;// console.log(username);game.login(username);console.log(game);// 隐藏login 显示选择;document.querySelector(".login").style.display = "none";document.querySelector(".game").style.display = "block";// 修改名称document.querySelector(".chioseusername").innerHTML = username;renderHeroes(game.player.heroes);
}function renderHeroes(heroes){console.log(heroes);document.querySelector(".heroView").innerHTML = "";heroes.forEach(hero=>{let heroItem = document.createElement("div");heroItem.classList.add("heroItem");heroItem.innerHTML = `<img src="${hero.ico}" /><span>${hero.name}</span>`;document.querySelector(".heroView").appendChild(heroItem);heroItem.onclick = function(){document.querySelector(".heroShow").innerHTML = `<img src="${hero.ico}" />`// 渲染技能renderSkills(hero.skills);// 渲染皮肤;renderSkins(hero.skins);}})
}function renderSkills(skills){document.querySelector(".skillsView").innerHTML = "";skills.forEach(skill=>{let img = document.createElement("img");img.src = skill.ico;document.querySelector(".skillsView").appendChild(img);img.onclick = function(){decorator(skill.release,hurt,skill,100);}})
}// 渲染皮肤
function renderSkins(skins){document.querySelector(".skinView").innerHTML="";document.querySelector(".skinShow").innerHTML = `<img src="${skins[0].img}" />`;skins.forEach(skin=>{let skinDiv = document.createElement("div");skinDiv.classList.add("skinItem");skinDiv.innerHTML = `<img src="${skin.ico}" /><span>${skin.name}</span>`;document.querySelector(".skinView").appendChild(skinDiv);skinDiv.onclick = function(){document.querySelector(".skinShow").innerHTML = `<img src="${skin.img}" />`;}})}// 切换 英雄 及皮肤;
document.querySelector(".heroBtn").onclick = function(){document.querySelector(".heroContainer").style.display = "block";document.querySelector(".skinContainer").style.display = "none";
}document.querySelector(".skinBtn").onclick = function(){document.querySelector(".heroContainer").style.display = "none";document.querySelector(".skinContainer").style.display = "block";
}
- 是按照之前讲的数据驱动的思想,所以这里一般都放一些渲染视图的逻辑。
- 具体都是一些DOM结构的基本操作,如果使用 vue 或者 react 开发的话,这些逻辑将会更简单。
六、 总结
- 这个案例能很好的体现面向对象的思想。其实无论是面向对象还是面向过程都有一定的好处,只是要根据实际需求来定。
- 巩固自己的同时也希望可以帮到大家~
面向对象02 - 案例:王者荣耀英雄选择相关推荐
- 王者荣耀英雄选择系统项目
"王者荣耀"英雄选择系统 先欣赏几张英雄图片 下面让我们一起进入正题! package Wangzexitong; import java.util.Scanner; /** * ...
- 王者荣耀英雄选择分析
目录 1. 压制与反压制->英雄选择 (1) BAN (2)压制 (3)英雄选择 2. 英雄分析 (1)单英雄分析 (2)多英雄分析 3.压制 (1)单英雄压制 (2)多英雄压制 4.召唤师技能 ...
- 小案例:搭建简易版王者荣耀英雄购买商城网页版
目录 一.网页赏析: 二.代码分三部分: 1.html代码: 2.main.css赏析: 3.初始化reset.css代码: 三.主要素材下载地址: 一.网页赏析: 二.代码分三部分: 1.html ...
- python爬取王者荣耀英雄素材图案例
import time import requests import threading from queue import Queue from urllib import parse import ...
- 【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类
目录 一.EM算法的步骤 二.EM算法的工作原理 三.在sklearn中创建GMM模型 四.工作流程 五.实战环节 1. 导包 2. 加载数据 3. 数据可视化分析 4. 特征工程 5. 数据规范化 ...
- 【攻略】程序员“王者”攻略,用Scrapy抓取104个王者荣耀英雄数据后...
本文由黄勇老师特约供稿 学习人数超5万人的<150讲轻松搞定Python网络爬虫>课作者 网易.360.华为特约Python讲师 说在前面. 周末无聊,翻翻手机,又重新打开了之前和兄弟们团 ...
- 图片链接用src不能被爬虫爬到吗_爬虫:带你一键爬取王者荣耀英雄皮肤壁纸
一.前言 王者荣耀这款手游,想必大家都玩过或听过,游戏里英雄有各式各样的皮肤,制作得很精美,有些拿来做电脑壁纸它不香吗.本文带你利用Python爬虫一键下载王者荣耀英雄皮肤壁纸. 1. 目标 创建一个 ...
- 常用英雄胜率怎么刷_王者荣耀英雄胜率怎么刷 王者荣耀刷英雄胜率的方法
王者荣耀英雄胜率怎么刷 王者荣耀刷英雄胜率的方法 王者荣耀英雄胜率怎么刷?玩家们都知道游戏每个英雄都只要上场就会有英雄胜利,多场次高胜率不仅看起来舒服,而且在游戏中队友也会感到格外安心.真的是这样吗, ...
- python爬虫入门------王者荣耀英雄及皮肤数据爬取项目
王者荣耀英雄及皮肤数据爬取项目 一:做前需知 笔者这段学习了一些爬虫的知识,然后做了一个小项目.接下来,我会把项目的流程展示出来. 运行环境:python 3.6.3.pycharm 2019-3-3 ...
最新文章
- QIIME 2教程. 31名词Glossary(2020.11)
- 离散度计算公式 python_被多种离散化场景困扰?8种python技巧!让数据处理更简单...
- java日期格式化代码的写法_Java中的`DateTimeFormatter`格式化代码中的`uuuu`与`yyyy`?...
- 人工智能中国专利技术分析报告发布,百度三年蝉联榜首
- Javaparser使用
- atmega328p引脚图_ATmega328P定时器详解
- mysql删除命令历史记录_MySQL历史命令记录清除
- [面试]HR最常用的20个面试问题及答案
- 【给初学者,大佬见笑】100%成功UEFI安装双硬盘单系统Ubuntu最合理分区安装指南+ubuntu20.04安装
- 训练faster rcnn报错:KeyError:‘max_overlaps’
- 微信小程序Day4学习笔记
- Anaconda更新报404:UnavailableInvalidChannel: The channel is not accessible or is invalid.error404
- c++语言解一元二次方程,C++ 求解一元二次方程
- 生存模型的C-index(C指数)
- 用VBA在word创建宏,功能是金额数字转换大写
- 品优购的界面设计要求_品优购项目
- ERP管理员培训报道
- 学习linux系统有什么用?
- 2022-2027年中国汽车传感器行业市场调研及未来发展趋势预测报告
- 2021年了,还没找到合适的报表软件?来看看这几款报表软件!