笔者最近都在玩Switch上的一个国产游戏,叫《风来之国》,强烈推荐给喜欢玩游戏的掘友们。如果你更喜欢游戏性、创新性而不是画面党,那么请相信我推荐的游戏吧~

image.png

毕竟这是一个开发者社区,本文希望借这款游戏来教大家如何学习游戏开发。

风来之国是一款像素风的动作角色扮演游戏(ARPG),游戏背景是一个人类的数量正在大幅度衰减,文明即将崩溃的世界。

2021-10-16 17_16_13.gif

本系列教程大概会有三篇

地图篇:基于图像的路墙系统(GraphicBased)

移动篇:角色和地图相对移动

互动篇:和地图上的元素互动

会不会写完看大家的反响:p

地图篇

地图决定了玩家所操控的游戏角色可以移动的范围和区域,游戏开发中有多种方式来实现地图。但无论是3D游戏,还是2D游戏,地图系统的底层一般都是基于2d图形。以风来之国游戏中下面这个场景为例

image.png

红色画笔是玩家操作角色允许移动的区域,我们要如何去实现呢?首先先把这个场景地图分层

地板层角色永远在地板之上

建筑层会根据角色的位置相互覆盖

因为我没有风来之国的美术资源

所以我这个灵堂级画师....

手绘了一个游戏地图

image.png

和原版可谓是毫无分别

搭架子

这里我们会使用 PIXI.js 引擎来搭建这个游戏系统,需要注意的是,我希望大家明白,文章重点在说原理,不是非得要用某个指定的引擎。

下面的代码可让玩家控制人上下左右移动。

<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js"></script>

<script type="text/javascript">

        //初始化PIXI

        const app = new PIXI.Application({

                backgroundColor:0xffffff

        });

        window.onload=function(){

                //将PIXI的渲染视图添加到网页body中

                document.body.appendChild(app.view);

                app.renderer.autoResize = true;

                app.renderer.resize(window.innerWidth, window.innerHeight);

                //加载资源

                app.loader.

                add('player', 'player.png').

                add('floor','floor.jpg').

                load((loader, resources) => {

                    //将资源添加到场景

                    const floor = new PIXI.Sprite(resources.floor.texture);

                    app.stage.addChild(floor);

                    const player = new PIXI.Sprite(resources.player.texture);

                    app.stage.addChild(player);

                    //将玩家图形的原点设置为中心点

                    player.anchor.x = 0.5;

                    player.anchor.y = 0.5;

                    app.ticker.add(() => {

                        //帧同步事件的回调

                    });

                    //上下左右键按下后角色移动

                    window.onkeydown=function (e) {

                            if(e.keyCode==37) {

                                 player.x-=2;

                            }else if(e.keyCode==39){

                                player.x+=2;

                            }

                            if(e.keyCode==38){

                                player.y-=2;

                            }else if(e.keyCode==40){

                                player.y+=2;

                            }

                        }

                });

        }

</script>

2021-10-18 16_40_40.gif

TADA! 现在我们的角色动起来了

现在这个移动不是很流畅,并且无法响应两个按键同时按下,也就是无法进行8向移动(↖↑↗ ←→ ↙↓↘),我们如此调整一下代码

app.ticker.add(() => {

    var nextX = player.x+moveDelta.x;

    var nextY = player.y+moveDelta.y;

    player.x=nextX;

    player.y=nextY;

});

window.onkeyup=function(e){

    if(e.keyCode==37||e.keyCode==39) {

        moveDelta.x=0;

    }else if(e.keyCode==38||e.keyCode==40){

        moveDelta.y=0;

    }

}

window.onkeydown=function (e) {

    if(e.keyCode==37) {

        moveDelta.x=-2;

    }else if(e.keyCode==39){

        moveDelta.x=2;

    }

    if(e.keyCode==38){

        moveDelta.y=-2;

    }else if(e.keyCode==40){

        moveDelta.y=2;

    }

}

2021-10-18 18_16_23.gif

丝滑多了,并且是8向移动的!

路墙系统

有些地方角色能去,有些地方不能去,这个要如何实现呢?在大部分游戏中,大致可以分为两种实现方式,其一是基于瓦片来实现,就是把地图分为不同的格子,用二维数组来决定哪些地方是路,哪些地方是墙,比如下面这个二维数组,1代表墙,0代表路。如果用相同尺寸的地板素材,可以很方便的建立路墙系统。

roadarea=[

    1,1,1,1,1,1,1,1,

    1,0,0,0,0,0,0,1,

    1,0,0,0,0,0,0,1,

    1,1,1,1,1,1,1,1

]

但这种方式比较适合由固定尺寸的瓦片图拼接的游戏,我将另起一系列文章来分享瓦片游戏系统的搭建。在本文中,我们使用基于图像的路墙系统GraphicBased。首先我们需要一个路墙区域标识图,大家注意看下图,这里不能行走的区域用红色来表示。

roadarea.jpg

相信大家已经明白我们要怎么做了!

我们只需要预判移动的目标位置下的像素是否为红色就不让继续移动...

下面我们来看看代码,注意,为了代码不过于长,这里贴的代码都是片段,要仔细阅读注释来理解或者对照我提供的源码

//将上图中的路墙标识图加载到系统中 

add('roadarea','roadarea.jpg')

const roadarea = new PIXI.Sprite(resources.roadarea.texture);

app.stage.addChild(roadarea);

//获得路墙标识图的全部像素数组

//格式[r,g,b,a],所以数组长度为路墙标识图的 宽x高x4

roadareaPixels = app.renderer.extract.pixels(roadarea);

//判断x,y坐标下的像素是否为墙体的标识颜色

function isHitWall(x,y){

    var width = 1728;//路墙标识图宽度

    var position = (width * y + x) * 4;//还原像素序号

    //取出颜色值r,g,b,a

    var r=roadareaPixels[position],g=roadareaPixels[position+1],b=roadareaPixels[position+2],a=roadareaPixels[position+3];

    //jpeg格式输出后颜色会略有损失,这里根据实际调整

    //就是判断x,y坐标下的颜色是否为红色

    if(r==255&&g<50){

            console.log("hit the wall");

            return true;

    }else{

            return false;

    } 

}

app.ticker.add(() => {

    var nextX = player.x+moveDelta.x;

    var nextY = player.y+moveDelta.y;

    //只有在移动的目标坐标下不是墙体颜色时才允许移动 

    if(!isHitWall(player.x,nextY)){

        player.y=nextY;

    }

    if(!isHitWall(nextX,player.y)){

        player.x=nextX;

    }

});

大家仔细看GIF,遇到墙时,调试信息输出了hit the wall

2021-10-18 20_25_33.gif

这部分代码有看不到明白的,可以仔细看看这篇文章《# 使用Javascript制作BadApple字符画视频》,其中使用的技术原理是一样的。

细节优化

现在判定的x,y来自角色的中心点,我们把角色的半径算上。并且隐藏路墙标识图,我们不需要看见它。

// app.stage.addChild(roadarea);

//在判定移动的目标位置时加上操控角色的半径,这里差不多是45

if(!isHitWall(player.x,nextY+45*moveDelta.y)){

    player.y=nextY;

}

if(!isHitWall(nextX+45*moveDelta.x,player.y)){

    player.x=nextX;

}

点赞(1) 打赏

评论列表 共有 0 条评论

暂无评论

热门产品

php编程基础教程.pptx|php编程培训,php,编程,基础,教程,pptx
php编程基础教程.pptx

历史上的今天:04月30日

热门专题

大理科技管理学校|大理科技管理学校,大理科技,大理科技中等职业技术学校,大理科技管理中等职业技术学校,大理科技学校
大理科技管理学校
小程序开发|微信小程序,小程序开发,小程序,小程序制作,微信小程序开发,小程序公司,小程序开发公司,分销,三级分销系统,分销系统
小程序开发
外贸网站建设|外贸网站建设,英文网站制作,英文网站设计,美国主机空间,外贸建站平台,多语言网站制作
外贸网站建设
安徽中源管业有限公司|安徽中源管业有限公司,安徽中源管业有限公司介绍,安徽中源管业有限公司电话,安徽中源管业有限公司地址,安徽中源管业有限公司厂家,安徽中源管业有限公司电力管,安徽中源管业有限公司管材
安徽中源管业有限公司
天麻的功效与作用吃法|天麻的功效与作用,天麻的功效与作用吃法,天麻炖什么治头痛最好,天麻的功效与作用禁忌,天麻多少钱一斤,天麻的功效与作用吃法及禁忌,天麻怎么吃效果最好,天麻粉的功效与作用,天麻怎么吃
天麻的功效与作用吃法
安徽中源管业|安徽中源管业,安徽中源管业mpp电力管,安徽中源管业cpvc电力管,安徽中源管业pe穿线管,安徽中源管业电力管,安徽中源管业排水管,安徽中源管业通信管,安徽中源管业管材
安徽中源管业
一年制中专|中专学历,中专是什么学历,中专是什么,中专有什么专业,中专升大专,一年制中专
一年制中专
昆明网站建设|昆明网站建设,昆明网站开发,昆明网站建设公司,昆明网站建设价格,昆明网站设计,昆明网站制作,网页设计,高端网站建设,高端网站设计
昆明网站建设

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部