王者荣耀英雄选择案例

  • 一、目标与说明
  • 二、实现效果
  • 三、写之前先分析
  • 四、类
    • 1. 玩家类
    • 2. 亚瑟类
    • 3. 鲁班类
    • 4.英雄基类
    • 5. 技能类和皮肤类
    • 6. 总结
  • 五、页面结构和逻辑
    • 1. 页面元素
    • 2. Style样式
    • 3. 逻辑操作
  • 六、 总结

一、目标与说明

  1. 还是注重逻辑分析,图片素材为游戏截屏抠图而成,不涉及王者炫酷的动画效果。
  2. 运用面向对象的思想,在这里我会分析王者荣耀运用了哪些对象,然后抽离里面的功能和方法、抽离成类、研究每个类之间的逻辑关系、把每个类模块化。
  3. 最终实现进入登录界面完成登陆、选择英雄、选择皮肤、释放技能等一系列功能。
  4. 为什么要用面向对象来做?王者荣耀上百个英雄,每个英雄又对应各自的皮肤和技能。按照面向对象思想,根据项目的特点,把类与类之间的逻辑关系写好,实现模块化功能,到时候上百个英雄只需要直接对类进行实例化就可以完成功能,代码更加易于管理和高效。
  5. 实现功能并不难,怎么划分对象、怎么划分功能、搞清楚对象与对象之间的关系是关键点。

二、实现效果

王者荣耀英雄选择案例效果图

三、写之前先分析

  • 写之前先分析一波:假设我已经知道面向对象的思想、知道什么是对象、类、原型、继承等,现在有了这样一个需求,我该怎么把思维从面向过程转变为面向对象呢?
  • 可以按照以下步骤:
  1. 根据需求研究对象,比如我今天就写两个英雄,不需要研究一大堆东西,一切从需求出发就行。要考虑有哪些对象?对象有哪些属性和方法?有什么特性?
  2. 抽象成类,提升复用性。如果是一个类,它就不止一个对象,可能有成百上千个对象,抽离这些对象中的一些共性的东西成类。如果某个对象有特殊的功能的话,就没必要抽离成类。
  3. 上一步研究完对象的共性,已经抽离成类了,这一步可以根据需求研究类的共性问题,即抽离类成为基类(父类),这时候就可以考虑继承的问题。但是是根据需求来,如果需求简单,就没必要这么做。
  4. 研究类之间的逻辑关系,研究这个类需要那个类,这个类调用那个类等等。
  • 在王者荣耀这个案例中,我列出来的对象有:亚瑟、鲁班、玩家、技能、皮肤、游戏管理类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. 总结

  1. 类与类之间的关系就说到这里啦,看似抽离了这么多类很麻烦,但其实一旦英雄数量多起来,玩家多起来,就会显现出这样做的好处,逻辑更清晰、更易于管理,哪里出现了bug也可以第一时间发现
  2. 所以大家还是慢慢学会转变自己的思想,从面向过程到面向对象

五、页面结构和逻辑

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 开发的话,这些逻辑将会更简单。

六、 总结

  1. 这个案例能很好的体现面向对象的思想。其实无论是面向对象还是面向过程都有一定的好处,只是要根据实际需求来定。
  2. 巩固自己的同时也希望可以帮到大家~

面向对象02 - 案例:王者荣耀英雄选择相关推荐

  1. 王者荣耀英雄选择系统项目

    "王者荣耀"英雄选择系统 先欣赏几张英雄图片 下面让我们一起进入正题! package Wangzexitong; import java.util.Scanner; /**  * ...

  2. 王者荣耀英雄选择分析

    目录 1. 压制与反压制->英雄选择 (1) BAN (2)压制 (3)英雄选择 2. 英雄分析 (1)单英雄分析 (2)多英雄分析 3.压制 (1)单英雄压制 (2)多英雄压制 4.召唤师技能 ...

  3. 小案例:搭建简易版王者荣耀英雄购买商城网页版

    目录 一.网页赏析: 二.代码分三部分: 1.html代码: 2.main.css赏析: 3.初始化reset.css代码: 三.主要素材下载地址: 一.网页赏析: 二.代码分三部分: 1.html ...

  4. python爬取王者荣耀英雄素材图案例

    import time import requests import threading from queue import Queue from urllib import parse import ...

  5. 【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类

    目录 一.EM算法的步骤 二.EM算法的工作原理 三.在sklearn中创建GMM模型 四.工作流程 五.实战环节 1. 导包 2. 加载数据 3. 数据可视化分析 4. 特征工程 5. 数据规范化 ...

  6. 【攻略】程序员“王者”攻略,用Scrapy抓取104个王者荣耀英雄数据后...

    本文由黄勇老师特约供稿 学习人数超5万人的<150讲轻松搞定Python网络爬虫>课作者 网易.360.华为特约Python讲师 说在前面. 周末无聊,翻翻手机,又重新打开了之前和兄弟们团 ...

  7. 图片链接用src不能被爬虫爬到吗_爬虫:带你一键爬取王者荣耀英雄皮肤壁纸

    一.前言 王者荣耀这款手游,想必大家都玩过或听过,游戏里英雄有各式各样的皮肤,制作得很精美,有些拿来做电脑壁纸它不香吗.本文带你利用Python爬虫一键下载王者荣耀英雄皮肤壁纸. 1. 目标 创建一个 ...

  8. 常用英雄胜率怎么刷_王者荣耀英雄胜率怎么刷 王者荣耀刷英雄胜率的方法

    王者荣耀英雄胜率怎么刷 王者荣耀刷英雄胜率的方法 王者荣耀英雄胜率怎么刷?玩家们都知道游戏每个英雄都只要上场就会有英雄胜利,多场次高胜率不仅看起来舒服,而且在游戏中队友也会感到格外安心.真的是这样吗, ...

  9. python爬虫入门------王者荣耀英雄及皮肤数据爬取项目

    王者荣耀英雄及皮肤数据爬取项目 一:做前需知 笔者这段学习了一些爬虫的知识,然后做了一个小项目.接下来,我会把项目的流程展示出来. 运行环境:python 3.6.3.pycharm 2019-3-3 ...

最新文章

  1. QIIME 2教程. 31名词Glossary(2020.11)
  2. 离散度计算公式 python_被多种离散化场景困扰?8种python技巧!让数据处理更简单...
  3. java日期格式化代码的写法_Java中的`DateTimeFormatter`格式化代码中的`uuuu`与`yyyy`?...
  4. 人工智能中国专利技术分析报告发布,百度三年蝉联榜首
  5. Javaparser使用
  6. atmega328p引脚图_ATmega328P定时器详解
  7. mysql删除命令历史记录_MySQL历史命令记录清除
  8. [面试]HR最常用的20个面试问题及答案
  9. 【给初学者,大佬见笑】100%成功UEFI安装双硬盘单系统Ubuntu最合理分区安装指南+ubuntu20.04安装
  10. 训练faster rcnn报错:KeyError:‘max_overlaps’
  11. 微信小程序Day4学习笔记
  12. Anaconda更新报404:UnavailableInvalidChannel: The channel is not accessible or is invalid.error404
  13. c++语言解一元二次方程,C++ 求解一元二次方程
  14. 生存模型的C-index(C指数)
  15. 用VBA在word创建宏,功能是金额数字转换大写
  16. 品优购的界面设计要求_品优购项目
  17. ERP管理员培训报道
  18. 学习linux系统有什么用?
  19. 2022-2027年中国汽车传感器行业市场调研及未来发展趋势预测报告
  20. 2021年了,还没找到合适的报表软件?来看看这几款报表软件!

热门文章

  1. TCP协议理解和用法以及三次握手四次分手
  2. SystemVerilog学习笔记
  3. 2020湖湘杯-CRYPTO-LFSRXOR
  4. Codeup 1009-1012 python
  5. 软件开发方式及风险分析
  6. 报错Cannot resolve symbol XXX
  7. 一个阿里P8的工程师,一年能赚多少钱?
  8. STM32:CCM的使用方法(GCC编译器)
  9. 水深火热的国内三大语音输入法对比
  10. 康佳U86V9电视怎么样?康佳U86V9电视参数配置评测