Drive 开车范例
代码
一样的引入global()
并且加载sprite,可以直接加载Aseprite导出的内容
复制 kaboom .global ();
loadRoot ( "/pub/img/" );
loadSprite ( "sky" , "sky.png" );
loadSprite ( "road" , "road.png" );
loadAseprite ( "car" , "car.png" , "car.json" );
loadSprite ( "apple" , "apple.png" );
loadSprite ( "pineapple" , "pineapple.png" );
初始化窗口
复制 init ({
width : 160 ,
height : 120 ,
scale : 4 ,
debug : true ,
});
创建场景main首先创建不同的层级,并且layers(names, [default])
传入"game"作为默认层
复制 layers ([
"bg" ,
"game" ,
"ui" ,
] , "game" );
创建变量
复制 const upBound = 40 ;
const lowBound = height () - 12 ;
const speed = 90 ;
let speedMod = 1 ;
制作滚动背景的方式 scroll backgrounds :
通过创建两张sprite(每一张都是屏幕的两倍宽度),然后创建action tag "road"
,在这里面加入一个移动的方法:移动速度为 speed * speedMod,并且判断,如果自身移动超过了屏幕左侧完全消失后再次出现在屏幕右侧。
复制 add ([
sprite ( "road" ) ,
pos ( 0 , 0 ) ,
layer ( "bg" ) ,
"road" ,
]);
add ([
sprite ( "road" ) ,
pos ( width () * 2 , 0 ) ,
layer ( "bg" ) ,
"road" ,
]);
action ( "road" , (r) => {
r .move ( - speed * speedMod , 0 );
if ( r . pos .x <= - width () * 2 ) {
r . pos .x += width () * 4 ;
}
});
创建玩家角色
复制 const car = add ([
sprite ( "car" ) ,
pos ( 24 , height () / 2 ) ,
color () ,
origin ( "center" ) ,
area ( vec2 ( - 12 , - 6 ) , vec2 ( 12 , 8 )) ,
{
speed : 100 ,
//这个地方因为每个component返回的是js obj,所以常规语法{key:value}
} ,
]);
播放角色(车)的动画,因为前面加载的Asprite的png的json文件中,包含了对于动画的定义
生成苹果🍎 和菠萝🍍 首先创建一个const来随机取出apple或者pineapple的字符,然后创建一个带有这个字符,对应的图像,还有action的tag "obj"
,出现在屏幕右边缘,在上下的边缘中间随机的位置。
定义的tag "obj"
主要是取让其想做运动,并且在超过屏幕范围之后销毁。
复制 loop ( 0.4 , () => {
const obj = randl ([
"apple" ,
"pineapple" ,
]);
add ([
sprite (obj) ,
"obj" ,
obj ,
pos ( width () , rand (lowBound , upBound)) ,
]);
});
action ( "obj" , (o) => {
o .move ( - speed * speedMod , 0 );
if ( o . pos .x <= - width ()) {
destroy (o);
}
});
然后处理碰撞事件:当car与带有"apple"
和"pineapple"
碰撞的时候,销毁对象并且增加快乐值
复制 // collision resolution
car .collides ( "apple" , (a) => {
destroy (a);
happiness .value += 50 ;
});
car .collides ( "pineapple" , (a) => {
destroy (a);
happiness .value += 100 ;
});
快乐值代表着一个简单的分数计算系统,首先创建一个hapiness
对象显示,在ui层显示,存放一个value
变量。并且创建一个action,当速度<1的时候,每帧分数-2,当速度>1的时候,每帧分数+1,并且让其text每帧更新数值。
复制 // happiness counter
const happiness = add ([
text ( "0" , 4 ) ,
pos ( 4 , 4 ) ,
layer ( "ui" ) ,
{
value : 0 ,
} ,
]);
happiness .action (() => {
if (speedMod < 1 ) {
happiness .value -= 2 ;
} else if (speedMod > 1 ) {
happiness .value += 1 ;
}
happiness .text = `happiness: ${ happiness .value } ` ;
});
输入系统 Input System
复制 // input
keyDown ( "up" , () => {
if ( car . pos .y > upBound) {
car .move ( 0 , - car .speed);
}
});
keyDown ( "down" , () => {
if ( car . pos .y < lowBound) {
car .move ( 0 , car .speed);
}
});
keyDown ( "left" , () => {
speedMod = 0.5 ;
car .animSpeed = 0.1 / speedMod;
});
keyDown ( "right" , () => {
speedMod = 3 ;
car .animSpeed = 0.1 / speedMod;
});
keyRelease ([ "left" , "right" ] , () => {
speedMod = 1 ;
car .animSpeed = 0.1 / speedMod;
});
其他
在代码下面还有另一个scene death
为结束页面,然后可以在上方例如吃到菠萝的时候让其进行跳转,值得注意的是这个scene("death", (score)=>{})
他接受一个 score
参数并显示这个 score
,如果是 go("death", 123)
他就会显示123
所以go() 的第二个即后面的参数就是传给这个scene的,相当于是不同scene之间的消息传递机制,没有定义的参数js默认就是undefined。
复制 ...
go ( "death" , happiness .value);
...
scene ( "death" , (score) => {
add ([
text (score , 24 ) ,
]);
add ([
text ( "press spacebar to play again" , 5 ) ,
pos ( 0 , - 20 ) ,
]);
keyPress ( "space" , () => {
//reload("main"); //这行删掉,比较早期的函数
go ( "main" );
});
});
方法
randl([])
意思是在数组中随机,现在已经改为 choose(arr)
: get a random element from the array
复制 const obj = randl ([
"apple" ,
"pineapple" ,
]);
关于绘制文字的方法 text(txt, size, [conf])
- conf 代表 config 更多配置,例如字体和宽度
复制 // note: this automatically gives the obj an 'area()' component
const obj = add ([
// content, size
text ( "oh hi" , 64 ) ,
]);
const obj = add ([
text ( "oh hi" , 64 , {
width : 120 , // wrap when exceeds this width (defaults to 0 no wrap)
font : "proggy" , // font to use (defaults to "unscii")
}) ,
]);
// update the content
obj .text = "oh hi mark" ;
进行场景的切换 go(name, [...args])
switch to a scene,arguments,可以传入任意类型,直接把 go("death", .....) 后面的所有参数原封不动传到scene函数的参数里。
复制 // go to "paused" scene when pressed "p"
scene ( "main" , () => {
let score = 0 ;
keyPress ( "p" , () => {
go ( "gameover" , score);
})
});
scene ( "gameover" , (score) => {
// display score passed by scene "main"
add ([
text (score) ,
]);
});