免费获取
|
论文天下网
|
原创毕业论文
|
论文范文
|
论文下载
|
计算机论文
|
论文降重
|
毕业论文
|
外文翻译
|
免费论文
|
开题报告
|
心得体会
|
全站搜索
当前位置:
论文天下网
->
免费论文
->
计算机论文
基于HTML5的跨平台游戏设计与实现(三)
JS同样提供便利的触摸(touchstart(e),touchend(e),touchmove(e)),鼠标(mouseup(e),mousedown(e),mousemove(e))事件等交互操作函数。let rect = canvas.getBoundingClientRect();获取到canvas的大小及其相对于窗口的位置。画面自适应章节我们已将canvas的大小设置为设备屏幕大小,因此该rect 值为就是{W,H,0,0};现在要获取鼠标点击位置相对与玩家的位置,以设置玩家的方块移动的方向。这里可以取巧为鼠标位置就是玩家方块要去的位置,因此直接设置 const mousePosX = e.offsetX - rect.left;player.position.x = mousePosX;这里e是JS提供的鼠标/触摸点击位置坐标对象,里面包含点击位置坐标以及距离窗口的坐标。
为了游戏的简单性,设置游戏子弹的发射为自动,每隔10帧就发射一次子弹,每次生成子弹的起始坐标等于玩家的position。
游戏开始菜单页,监听mousedown和touchstart事件,等待玩家有点击或者触摸时,则设置游戏为开始状态。
五、游戏测试
在PC端OSX系统用Chrome浏览器打开index.html文件,按下F12,开启浏览器的手机模式。我们看到一个画面如图所示,游戏文字显示正常,文字动画正常闪缩。
图5-1 游戏开始界面
根据提示,点击游戏窗口屏幕,画面正常跳转到游戏场景页。开始如图5-2所示,分数,难度,最高分等游戏交互文本显示正常。子弹攻击到敌人后,敌人正常炸裂,并且分数增加。
图5-2 游戏HUD界面
在游戏窗口点击鼠标左键不放,并拖动鼠标,屏幕最下放玩家方块跟随鼠标移动正常如图5-3和图5-4所示。
图5-3 玩家方块
图5-4 玩家方块向左移动
六、结论
通过基于H5的跨平台小游戏开发,基本上体现了H5游戏的开发过程,最后也已经实现了一个跨平台游戏所需要的基本功能要素。H5的游戏开发过程较为简单,只要写好游戏规则和游戏部件绘制,开发游戏是很方便的,而所花时间也和开发游戏的规模,规则,内容复杂度相关。H5作为最新的web语言标准,此次开发中过程中,采用了JS最新版本ES6语法让代码耦合大大降低,面向对象的class新特性也上不同功能的代码分离更干净,相同功能代码更成体系。既方便阅读,又方便逻辑组装。对于后期修改整理有着极大方便。尽管所有功能并不是每个版本的浏览器都能兼容,但是对于canvas标签来说,随着时间的推移,支持H5的浏览器会越来越多,越来越完善与规范。2019年连微软的都放弃了IE转而用支持H5特性的更好的浏览器开源项目Chromium来重构自己的Edge浏览器。如今来说,基本适用无论是PC端还是智能手机端,都对H5有很好的支持。
附录 游戏源码
1. html文件源码
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=0.5, maximum-scale=1.0, minimum-scale=0.5">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>方块进攻</title>
<style type="text/css">
* {margin: 0;border: 0;padding: 0;overflow: hidden;}
body{background-color:rgba(0,0,0,0.8);}
</style>
</head>
<body>
<canvas id="game" onresize="View.resize"></canvas>
</body>
<script src="press_key.js"></script>
<script src="game.js"></script>
</html>
2. Press_key.js文件源码
let mouseDown=(e)=>{
keys[82] = true;
}
let mouseUp=(e)=>{
keys[82] = false;
}
let mouseMove=(e) =>{
let rect = canvas.getBoundingClientRect();
const mousePosX = e.offsetX - rect.left;
if (player && !gameOver) player.position.x = mousePosX;
}
let touchStart = (e)=>{
keys[82] = true;
}
let touchEnd = (e)=>{
keys[82] = false;
}
let touchMove=(e) =>{
const rect = canvas.getBoundingClientRect();
const mousePosX = e.touches[0].pageX - rect.left;
if (player && !gameOver) player.position.x = mousePosX;
}
3. Game.js文件源码
// 全局变量
//-----------------
let frames,W,H,W2,H2,player,
canvas,
ctx,
gameMode='menu';
let bgColor = "rgba(0,0,0,0.8)"
let ready;
let enemyScore;
let spawntime;
let difficulty;
let score=0;
let highScore=localStorage.getItem('highScore');
if (!highScore) highScore = 0
let gameOver=false;
let keys = [],entities = [], units = [], effects = [];
let OS_PC = "pc",
OS_IPHONE = "iPhone",
OS_IPAD = "iPad",
OS_ANDROID = "Android";
let Lib = {
os: OS_PC,
canTouch: false,
ios: false,
rand:(n=1)=>{
return Math.floor(Math.random() * n);
},
rangeRand:(min,max)=>{
return Math.floor(Math.random() * (max - min + 1)) + min;
},
rgba:(r, g, b, a=1)=>{
return `rgba(${r},${g},${b},${a})`;
},
randomColor:(min=0,max=255)=>{
let r = Lib.rangeRand(min,max);
let g = Lib.rangeRand(min,max);
let b = Lib.rangeRand(min,max);
return Lib.rgba(r,g,b);
},
overlaps:(entityA,entityB)=>{
let aSize = entityA.size;
let x1a = entityA.position.x;
let x2a = x1a + aSize;
let y1a = entityA.position.y;
let y2a = y1a + aSize;
let bSize = entityB.size;
let x1b = entityB.position.x;
let x2b = x1b + bSize;
let y1b = entityB.position.y;
let y2b = y1b + bSize;
return (x1a < x2b && x2a > x1b && y1a < y2b && y2a > y1b);
}
};
((userAgent)=>{
if (userAgent.indexOf(OS_IPHONE) > -1) {
Lib.os = OS_IPHONE;
Lib.canTouch = true;
Lib.ios = true;
} else if (userAgent.indexOf(OS_IPAD) > -1) {
Lib.os = OS_IPAD;
Lib.ios = true;
Lib.canTouch = true;
} else if (userAgent.indexOf(OS_ANDROID) > -1) {
Lib.os = OS_ANDROID;
Lib.canTouch = true;
Lib.android = true;
}
})(navigator.userAgent);
window.onload = ()=>{
Game.init();
}
//全局 函数
//----------------
let Game = {
init:()=>{
canvas = document.getElementById('game');
View.resize();
Game.reset();
Game.event();
gameMode = "menu";
Game.loop();
},
start:()=>{
gameMode = "game";
keys[121] = true;
ctx.textAlign = "left";
//Spawn player
player = new Player();
player.position.set(W2,H-player.size);
units.push(player);
},
loop() {
switch (gameMode) {
case "menu":
View.menu();
break;
case "game":
Game.update();
View.game();
break;
case "over":
View.gameOver();
break;
}
frames ++;
window.requestAnimationFrame(Game.loop);
},
update:()=>{
if(frames % 1800 === 0){
Game.increaseDifficulty();
}
if(frames%spawntime === 0){
Game.spawnEnemy();
}
units.forEach((e,index)=>{
if(e.alive){
e.update();
} else {
units.splice(index,1);
}
})
effects.forEach((e,index)=>{
if(e.alive){
e.update();
} else {
effects.splice(index,1);
}
})
Game.checkCollide();
},
checkCollide:()=>{
let len = units.length;
let l = 0;
let r = len - 1;
while (l != r){
let a = units[l];
let b = units[r];
if (Lib.overlaps(a,b)){
if(a.name === "Enemy"){
a.alive = false;
b.alive = false;
View.boomEffect(a);
score ++;
}
if(b.name === "Enemy"){
a.alive = false;
b.alive = false;
View.boomEffect(a);
score ++;
}
}
l++;
if(l != r){
r--;
}
}
},
event:()=>{
canvas.oncontextmenu =()=>{return false;}
if(Lib.canTouch){
canvas.addEventListener('touchstart', touchStart, false);
canvas.addEventListener('touchend', touchEnd, false);
canvas.addEventListener("touchmove", touchMove, false);
}else {
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
},
reset:()=>{
if (score > highScore){
highScore = score;
localStorage.setItem('highScore',highScore)
}
ready = true;
frames = 0;
enemyScore = 0;
difficulty = 1;
score = 0;
spawntime = 120;
gameOver = false;
entities = [];
player = null;
},
increaseDifficulty(){
difficulty += 1;
if (spawntime > 20) spawntime -= 10;
},
spawnEnemy(){
let e = new Enemy();
let px = Lib.rand(W);
let py = -e.size;
e.position.set(px,py);
let r = Lib.rand();
if (r > .7){
AI.line(e);
} else if (r > .4){
AI.avg(e);
} else {
AI.triangular(e);
}
units.push(e);
}
};
let View = {
resize: ()=>{
W = window.innerWidth;
H = window.innerHeight;
W2 = window.innerWidth>>1;
H2 = window.innerHeight>>1;
canvas.width = W;
canvas.height = H;
ctx = canvas.getContext("2d");
ctx.font = "32px Arial";
ctx.textAlign = "center";
ctx.strokeStyle = "rgba(255,255,255,1)";
ctx.fillStyle = "rgba(220,220,255,1)";
},
menu:()=>{
View.clear();
ctx.fillStyle = "rgba(220,220,255,1)";
ctx.fillText("方块进攻", W2, H2>>1);
ctx.fillText("", W2, (H2>>1)+100);
ctx.fillStyle = Lib.rgba(125 - (frames % 60) * 3, 255 - (frames % 60) * 3, 125 - (frames % 60) * 3,1);
ctx.fillText("点击屏幕开始", W2, H2);
if (keys[82]) {
Game.start();
}
},
clear:()=>{
ctx.fillStyle = bgColor;
ctx.fillRect(0,0,W, H);
},
game:()=>{
View.clear();
if (gameOver){
gameMode = "menu";
Game.reset();
return;
}
View.drawEntities();
View.drawScore();
},
drawEntities:()=>{
units.forEach((e)=>{
e.render();
})
effects.forEach((e)=>{
e.render();
})
},
gameOver:()=>{
View.clear();
View.drawStatic();
View.drawScore();
ctx.fillStyle = Lib.rgba(125 - (frames % 60) * 3, 255 - (frames % 60) * 3, 125 - (frames % 60) * 3,1);;
ctx.fillText("游戏结束",W2 - 220,H2);
if (keys[82]) {
gameMode = "menu";
}
},
drawStatic:()=>{
let s = 30 ;
for (let x = 0; x < W; x+=s){
for (let y = 0; y < W; y+=s){
let n = Lib.rangeRand(0,60);
ctx.fillStyle = Lib.rgba(n,n,n,Math.random() * frames%60);
ctx.fillRect(x,y,s,s);
}
}
},
boomEffect:(entity)=>{
let particleCount = Math.floor((Math.random() * 6) + 3);
for (let i = 0; i < particleCount; i++){
let p = new Particle();
p.color = entity.color;
p.size = Math.floor((Math.random() * entity.size/2) + 5);
p.position.set(entity.position.x+entity.size/2,entity.position.y+entity.size/2);
effects.push(p);
}
},
drawScore:()=>{
ctx.fillStyle = "#CCFF99";
ctx.fillText("分数: " + score,20,40);
ctx.fillText("最高分: " + highScore,20,80);
let enemyScoreString = "";
for (let i = 0; i < enemyScore; i++){
enemyScoreString += "X";
}
ctx.fillStyle = "#FF6666";
ctx.fillText(enemyScoreString,20,120);
ctx.fillText("难度: " + difficulty,W2,30);
}
}
let AI = {
line:(entity)=>{
entity.velocity.x = W2;
entity.update = function(){
if(frames%20 === 0){
if(this.position.x == 0){
this.velocity.x = W2;
}else if(this.position.x == W){
this.velocity.x = -W2;
}
}else{
this.velocity.x = 0;
}
this.velocity.y = 1;
Entity.prototype.update.call(this);
}
},
avg:(entity)=>{
entity.update = function(){
this.velocity.x = this.size;
this.velocity.y = 1+difficulty;
Entity.prototype.update.call(this);
}
},
triangular:(entity)=>{
entity.update = function(){
this.velocity.x = this.size;
this.velocity.y = this.size/2;
Entity.prototype.update.call(this);
}
}
}
// class ================
class Vector2{
constructor(x,y){
this.x = x;
this.y = y;
}
set(a,b){
this.x = a;
this.y = b;
}
}
class Entity{
constructor(){
this.name = "Entity";
this.size = 25*2;
this.position = new Vector2(0,0);
this.velocity = new Vector2(0,0);
this.color = "#FFF";
this.alive = true;
}
sayName(){
console.log(this.name);
}
update(){
if (this.position.x == 0 || this.position.x == W) {
this.velocity.x = (-this.velocity.x)
}
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
if (this.position.x + this.size > W) {
this.position.x = W - this.size;
}
if (this.position.x - this.size < 0) {
this.position.x = 0
}
}
render(){
ctx.fillStyle = this.color;
ctx.fillRect(this.position.x,this.position.y,this.size,this.size);
}
}
class Enemy extends Entity{
constructor(){
super();
this.name = "Enemy";
this.size = Lib.rangeRand(40,100);
this.color = Lib.randomColor();
}
}
class Player extends Entity{
constructor(){
super();
this.name = "Player";
this.color = Lib.randomColor();
this.cd = 10;
this.bulletSpeed = -30;
}
update() {
super.update();
if(frames%this.cd===0){
let bullet = new Bullet();
let offset = (player.size>>1) - (bullet.size>>1) ;
bullet.position.set(player.position.x + offset, player.position.y - offset);
bullet.velocity.y = this.bulletSpeed;
units.push(bullet);
}
}
}
class Particle extends Entity{
constructor(){
super();
this.name = "Particle";
this.size = 10*2;
this.time = 0;
this.maxTime = Lib.rangeRand(10,20);
this.velocity.x = Lib.rangeRand(10,-20);
this.velocity.y = Lib.rangeRand(10,30);
}
update(){
super.update();
this.time += 1;
if (this.time >= this.maxTime){
this.alive = false;
}
}
}
class Bullet extends Entity{
constructor(){
super();
this.name = "Bullet";
this.size = 10*2;
this.color = Lib.randomColor();
this.particlesDelay = 5;
}
update(){
if (this.position.y < 0) {
this.alive = false;
return;
}
super.update();
if (frames%this.particlesDelay === 0){
let p = new Particle();
let b_size = (this.size>>1);
p.size = Lib.rangeRand(5,b_size);
p.color = Lib.randomColor();
p.position.x = this.position.x + (p.size>>1);
p.position.y = this.position.y - (p.size>>1);
effects.push(p);
}
}
}
首页
上一页
1
2
3
下一页
尾页
3
/3/3
相关论文
上一篇
:
计算机网络安全浅析
下一篇
:
防火墙技术浅析
推荐论文
本专业最新论文
Tags:
基于
HTML5
跨平台
游戏
设计
实现
【
返回顶部
】
相关栏目
自动化相关
计算机论文
工程管理论文
法律论文
医学论文
人力资源
电子专业
电气工程
英语论文
行政管理
电子商务
社科文学
教育论文
物流专业
金融专业
财务管理
会计专业
化学化工材料科学
电子通信
环境科学
经济类
机械模具类
报告,总结,申请书
其他专业论文