Created
August 9, 2015 09:26
-
-
Save gjz010/2f26fe4c03103dca97a9 to your computer and use it in GitHub Desktop.
弹幕太鼓 Bilitaiko v0.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var NOTES=[]; //留空 | |
/** | |
曲谱格式 | |
绝对时间|类型 | |
b r bg rg l(长鼓,不予实现)f(拨浪鼓,不予实现)bl(气球,不予实现) | |
*/ | |
/** | |
BiliTaiko v0.1 | |
弹幕太鼓 通用代码 | |
by gjz010 | |
TODO LIST: | |
加入鼓点 Done | |
(用Timer计时不太可靠,看看能不能用播放头计时) Done | |
鼓点与按键的配合 Done | |
(突然有了一个绝妙的解决“连环鼓”的方法:敲下一个鼓点判定生效立刻复位) Done | |
UI美化(加一道光) Done虽然一点也不美 | |
Record Mode Undone 没什么用途,没有经过测试,有兴趣可以将RECORD_MODE并加入必要代码打开试试 | |
*/ | |
//常量变量定义 | |
//按键定义 | |
//65 83 68 37 40 39 100 101 102 | |
var KEY_BLUE_LEFT = 83; | |
var KEY_BLUE_RIGHT = 68; | |
var KEY_RED_LEFT = 100; | |
var KEY_RED_RIGHT = 101; | |
var KEY_RECORD_OPT = 38; | |
var TIMEOUT_MAX = 2147483647; | |
var DBLKEY_RESPOND_TIMEOUT = 43; | |
var SHIFT = 3750; //延迟5s为准 | |
var CHECK_INTERVAL = 100; | |
var RECORD_MODE = false; //录制模式 为了方便编写谱面的= = 完全是个鸡肋!!! | |
var VALID_BEAT = 150; | |
var VERSION = "BiliTaiko v0.1"; | |
var SONGNAME = "4分33秒 -约翰·凯奇"; | |
//令牌变量定义 | |
var blue_left = false; | |
var blue_right = false; | |
var red_left = false; | |
var red_right = false; | |
var blue_judge_dbl_l = false; | |
var blue_judge_dbl_r = false; | |
var red_judge_dbl_l = false; | |
var red_judge_dbl_r = false; | |
//句柄变量定义 | |
var taiko_trigger; | |
var taiko_controller; | |
var taiko_belt; | |
var taiko_float_belt; | |
var taiko_power; | |
var text_combo; | |
var text_score; | |
//游戏逻辑变量 | |
var taikos = []; | |
var combos = 0; | |
var score = 0; | |
var note_clone; | |
var note_in_record = []; | |
var game_started = false; | |
//用到的算法类函数 | |
//画圆弧的方法,摘自Wiki | |
function drawArc(dx, dy, r, ang, color, rttz, p) { | |
var myObj = $.createShape({ | |
x: dx, | |
y: dy, | |
lifeTime: 0, | |
parent: p | |
}); | |
myObj.graphics.beginFill(color); | |
myObj.graphics.lineStyle(1); | |
var a = ang / 180 * Math.PI / 0.01; | |
myObj.graphics.lineTo(r, 0); | |
for (var i = 0; i <= a; i++) { | |
myObj.graphics.curveTo(Math.cos((i - 0.5) * 0.01) * r, Math.sin((i - 0.5) * 0.01) * r, Math.cos(i * 0.01) * r, Math.sin(i * 0.01) * r); | |
} | |
myObj.graphics.endFill(); | |
myObj.rotationZ = rttz; | |
return myObj; | |
}; | |
function judgeTimeout() { | |
if (taikos.length == 0) { | |
return; | |
} | |
if (taikos[0].entity.x < 60) { | |
target = taikos[0]; | |
taikos.shift(); | |
target.entity.remove(); | |
display_wrong("Miss"); | |
combos = 0; | |
} | |
} | |
//开始游戏 | |
function start() { | |
ScriptManager.clearEl(); | |
ScriptManager.clearTrigger(); | |
ScriptManager.clearTimer(); | |
Player.seek(0); | |
taikos = []; | |
drawBg(); | |
drawBilibili(30, 30); //画一个小电视 | |
taiko_belt = drawBelt(60, 140); | |
taiko_float_belt = $.createCanvas({ | |
x: 60, | |
y: 140, | |
lifeTime: 0 | |
}); | |
taiko_controller = drawTaiko(60, 180); | |
taiko_power = drawPower(0, 0); | |
drawVersion(); | |
drawSongName(220, 221, SONGNAME); | |
note_clone = clone(NOTES); | |
startDelta(); | |
interval(judgeTimeout, 100, 0); | |
Player.keyTrigger(onKeyDown, TIMEOUT_MAX); //获取按下事件 | |
Player.keyTrigger(onKeyUp, TIMEOUT_MAX, true); //获取松开事件 | |
Player.play(); | |
} | |
//Background | |
function drawBg() { | |
var bg = $.createShape({ | |
x: 0, | |
y: 0, | |
lifeTime: 0 | |
}); | |
bg.graphics.beginGradientFill("linear", [16750848, 16777011], [1, 1], [57, 255], $.createGradientBox(166, 0, 0, 0, 0), "reflect"); | |
//0xB88A00, 0xF5B800,0xFF6633 | |
bg.graphics.drawRect(0, 0, Player.width, Player.height); | |
bg.graphics.endFill(); | |
return bg; | |
} | |
//画小电视的代码 | |
function drawBilibili(dx, dy) { | |
var tv = $.createShape({ | |
x: dx, | |
y: dy, | |
lifeTime: 0 | |
}); | |
var g = tv.graphics; | |
g.beginFill(0xFFFFFF); | |
g.lineStyle(2); | |
g.drawCircle(30, 20, 10); | |
g.drawCircle(50, 20, 10); | |
g.endFill(); | |
g.beginFill(0xFFFFFF); | |
g.drawRoundRect(0, 20, 80, 64, 10); | |
g.endFill(); | |
g.moveTo(30, 40); | |
g.lineTo(10, 50); | |
g.moveTo(50, 40); | |
g.lineTo(70, 50); | |
g.moveTo(20, 60); | |
g.lineTo(30, 70); | |
g.lineTo(40, 60); | |
g.lineTo(50, 70); | |
g.lineTo(60, 60); | |
} | |
function drawBelt(dx, dy) { | |
var beltc = $.createCanvas({ | |
x: dx, | |
y: dy, | |
lifeTime: 0 | |
}); | |
var body = $.createShape({ | |
x: 0, | |
y: 0, | |
lifeTime: 0, | |
parent: beltc | |
}); | |
var g = body.graphics; | |
g.beginFill(0xffffff); | |
g.lineStyle(1); | |
g.drawRect(0, 0, 640, 80); | |
g.endFill(); | |
g.drawCircle(100, 40, 30); | |
return beltc; | |
} | |
function drawPower(dx, dy) { | |
var powerc = $.createCanvas({ | |
x: dx, | |
y: dy, | |
lifeTime: 0 | |
}); | |
var body = $.createShape({ | |
x: 0, | |
y: 0, | |
lifeTime: 0, | |
parent: powerc | |
}); | |
var g = body.graphics; | |
g.beginFill(0xffffff); | |
g.lineStyle(1); | |
g.drawCircle(20, 20, 20); | |
g.endFill(); | |
text_score = $.createComment("", { | |
x: 40, | |
y: -10, | |
lifeTime: 0, | |
color: 0xFFFFFF, | |
fontsize: 40, | |
alpha: 1, | |
parent: powerc | |
}); | |
update_score(0); | |
return powerc; | |
} | |
//生成鼓的函数 | |
//用飞过的弹幕作为鼓点 <- (╯°口°)╯(┴—┴我当时是怎么想到这种脑残主意的 | |
function createDrum(type, size) { | |
var dc = Utils.rgb(255, 255, 255); | |
if (type == 0) { | |
dc = Utils.rgb(255, 0, 0); | |
} | |
if (type == 1) { | |
dc = Utils.rgb(0, 0, 255); | |
} | |
/*var drum = $.createComment("●", { | |
motion: { | |
x: { | |
fromValue: 640, | |
toValue: -250, | |
lifeTime: 2, | |
easing: "None" | |
} | |
}, | |
y: (size ? 4 : 15), | |
lifeTime: 5, | |
color: dc, | |
fontsize: (size ? 60 : 40), | |
alpha: 1, | |
parent:taiko_float_belt | |
}); | |
*/ | |
var drum = $.createShape({ | |
/*motion: { | |
x: { | |
fromValue: 640, | |
toValue: -250, | |
lifeTime: 2, | |
easing: "None" | |
} | |
},*/ | |
x: 640, | |
y: 40, | |
lifeTime: 5, | |
parent: taiko_float_belt | |
}); | |
var g = drum.graphics; | |
g.beginFill(dc); | |
g.lineStyle(1); | |
g.drawCircle(0, 0, (size ? 30 : 20)); | |
g.endFill(); | |
var t = Tween.to(drum, { | |
x: -250 | |
}, | |
2); | |
t.play(); | |
var obj = { | |
type: type, | |
size: size, | |
entity: drum, | |
tween: t | |
}; | |
taikos.push(obj); | |
return obj; | |
} | |
//绘制一个太鼓 | |
function drawTaiko(dx, dy) { | |
var tc = $.createCanvas({ | |
x: dx, | |
y: dy, | |
lifeTime: 0 | |
}); | |
var bc = $.createShape({ | |
x: 0, | |
y: 0, | |
parent: tc, | |
lifeTime: 0 | |
}); | |
bc.graphics.beginFill(0xffffff); | |
bc.graphics.lineStyle(1); | |
bc.graphics.drawCircle(0, 0, 60); | |
bc.graphics.endFill(); | |
var bl = drawArc(0, 0, 60, 180, 0x3cc4c4, 90, tc); | |
var br = drawArc(0, 0, 60, 180, 0x3cc4c4, -90, tc); | |
bl.visible = false; | |
br.visible = false; | |
var sc = $.createShape({ | |
x: 0, | |
y: 0, | |
parent: tc, | |
lifeTime: 0 | |
}); | |
sc.graphics.beginFill(0xffffff); | |
sc.graphics.lineStyle(1); | |
sc.graphics.drawCircle(0, 0, 50); | |
sc.graphics.endFill(); | |
sc.graphics.moveTo(0, 60); | |
sc.graphics.lineTo(0, -60); | |
var rl = drawArc(0, 0, 50, 180, 0xff0000, 90, tc); | |
var rr = drawArc(0, 0, 50, 180, 0xff0000, -90, tc); | |
rl.visible = false; | |
rr.visible = false; | |
return { | |
bluel: bl, | |
bluer: br, | |
redl: rl, | |
redr: rr, | |
canvas: tc | |
}; | |
} | |
//按键侦听设置 | |
//(╯°口°)╯(┴—┴ 我总有一天要把多键识别写成API | |
function onHitBlue(right, big) { | |
if (taikos.length == 0) { | |
return; | |
} | |
target = taikos[0]; | |
if (target.entity.x > VALID_BEAT) { | |
return; | |
} | |
if (target.type == 1) { | |
taikos.shift(); | |
drum_beaten(target); | |
var s = 20; | |
s = s + ((Math.min((Math.floor(combos / 10)), 10)) * 5); | |
if (big & (target.size)) { | |
s *= 2; | |
} | |
update_score(s); | |
blue_judge_dbl_l = false; | |
blue_judge_dbl_r = false; | |
//target.entity.remove(); | |
} else { | |
taikos.shift(); | |
target.entity.remove(); | |
display_wrong("X"); | |
combos = 0; | |
} | |
//trace("once_blue_" + (right ? "right": "left")+(big?"_big":"")); | |
} | |
function onHitRed(right, big) { | |
if (taikos.length == 0) { | |
return; | |
} | |
target = taikos[0]; | |
if (target.entity.x > VALID_BEAT) { | |
return; | |
} | |
if (target.type == 0) { | |
taikos.shift(); | |
drum_beaten(target); | |
var s = 20; | |
s = s + ((Math.min((Math.floor(combos / 10)), 10)) * 5); | |
if (big & (target.size)) { | |
s *= 2; | |
} | |
update_score(s); | |
red_judge_dbl_l = false; | |
red_judge_dbl_r = false; | |
//target.entity.remove(); | |
} else { | |
taikos.shift(); | |
target.entity.remove(); | |
display_wrong("X"); | |
combos = 0; | |
} | |
//trace("once_red_" + (right ? "right": "left")+(big?"_big":"")); | |
} | |
function onKeyDown(key) { | |
switch (key) { | |
case KEY_BLUE_LEFT: | |
taiko_controller.bluel.visible = true; | |
if (!blue_left) { | |
if (blue_judge_dbl_r) { | |
onHitBlue(false, true); | |
blue_judge_dbl_r = false; | |
} else { | |
blue_judge_dbl_l = true; | |
timer(function() { | |
if (blue_judge_dbl_l) { | |
blue_judge_dbl_l = false; | |
onHitBlue(false, false); | |
} | |
}, | |
DBLKEY_RESPOND_TIMEOUT); | |
} | |
} | |
blue_left = true; | |
break; | |
case KEY_BLUE_RIGHT: | |
taiko_controller.bluer.visible = true; | |
if (!blue_right) { | |
if (blue_judge_dbl_l) { | |
onHitBlue(true, true); | |
blue_judge_dbl_l = false; | |
} else { | |
blue_judge_dbl_r = true; | |
timer(function() { | |
if (blue_judge_dbl_r) { | |
blue_judge_dbl_r = false; | |
onHitBlue(true, false); | |
} | |
}, | |
DBLKEY_RESPOND_TIMEOUT); | |
} | |
} | |
blue_right = true; | |
break; | |
case KEY_RED_LEFT: | |
taiko_controller.redl.visible = true; | |
if (!red_left) { | |
if (red_judge_dbl_r) { | |
onHitRed(false, true); | |
red_judge_dbl_r = false; | |
} else { | |
red_judge_dbl_l = true; | |
timer(function() { | |
if (red_judge_dbl_l) { | |
red_judge_dbl_l = false; | |
onHitRed(false, false); | |
} | |
}, | |
DBLKEY_RESPOND_TIMEOUT); | |
} | |
} | |
red_left = true; | |
break; | |
case KEY_RED_RIGHT: | |
taiko_controller.redr.visible = true; | |
if (!red_right) { | |
if (red_judge_dbl_l) { | |
onHitRed(true, true); | |
red_judge_dbl_l = false; | |
} else { | |
red_judge_dbl_r = true; | |
timer(function() { | |
if (red_judge_dbl_r) { | |
red_judge_dbl_r = false; | |
onHitRed(true, false); | |
} | |
}, | |
DBLKEY_RESPOND_TIMEOUT); | |
} | |
} | |
red_right = true; | |
break; | |
} | |
} | |
function onKeyUp(key) { | |
switch (key) { | |
case KEY_BLUE_LEFT: | |
taiko_controller.bluel.visible = false; | |
blue_left = false; | |
if (blue_judge_dbl_l) { | |
blue_judge_dbl_l = false; | |
onHitBlue(false, false); | |
} | |
break; | |
case KEY_BLUE_RIGHT: | |
taiko_controller.bluer.visible = false; | |
blue_right = false; | |
if (blue_judge_dbl_r) { | |
blue_judge_dbl_r = false; | |
onHitBlue(true, false); | |
} | |
break; | |
case KEY_RED_LEFT: | |
taiko_controller.redl.visible = false; | |
red_left = false; | |
if (red_judge_dbl_l) { | |
red_judge_dbl_l = false; | |
onHitRed(false, false); | |
} | |
break; | |
case KEY_RED_RIGHT: | |
taiko_controller.redr.visible = false; | |
red_right = false; | |
if (red_judge_dbl_r) { | |
red_judge_dbl_r = false; | |
onHitRed(true, false); | |
} | |
break; | |
default: | |
//trace(note_in_record.toString()); | |
break; | |
} | |
} | |
//差量计时器逻辑 | |
function deltaTimer() { | |
var current = note_clone.shift(); | |
var parts = current.split("|"); | |
switch (parts[1]) { | |
case "r": | |
createDrum(0, false); | |
break; | |
case "rg": | |
createDrum(0, true); | |
break; | |
case "b": | |
createDrum(1, false); | |
break; | |
case "bg": | |
createDrum(1, true); | |
break; | |
} | |
if (note_clone.length != 0) { | |
var nextone = note_clone[0]; | |
var nextparts = nextone.split("|"); | |
var delta = parseInt(nextparts[0]) - Player.time + SHIFT; | |
timer(deltaTimer, delta); | |
} | |
} | |
function startDelta() { | |
var current = note_clone[0]; | |
var parts = current.split("|"); | |
var delta = parseInt(parts[0]) - Player.time + SHIFT; | |
timer(deltaTimer, delta); | |
} | |
//动画逻辑 | |
function drum_beaten(target) { | |
target.tween.stop(); (Tween.to(target.entity, { | |
x: -60, | |
y: -140 | |
}, | |
0.2)).play(); | |
combos = combos + 1; | |
if (text_combo) { | |
text_combo.remove(); | |
} | |
var posx = ( - 10 - ((combos.toString()).length) * 10); | |
text_combo = $.createComment(combos.toString(), { | |
x: posx, | |
y: -35, | |
lifeTime: 1, | |
color: 0xFFCC33, | |
fontsize: 60, | |
alpha: 1, | |
parent: taiko_controller.canvas | |
}); | |
} | |
function display_wrong(str) { | |
if (text_combo) { | |
text_combo.remove(); | |
} | |
var posx = ( - 10 - (str.length) * 10); | |
text_combo = $.createComment(str, { | |
x: posx, | |
y: -35, | |
lifeTime: 1, | |
color: 0xFF0000, | |
fontsize: 60, | |
alpha: 1, | |
parent: taiko_controller.canvas | |
}); | |
} | |
function update_score(delta) { | |
score = score + delta; | |
text_score.text = "Scores:" + score.toString(); | |
} | |
function drawVersion() { | |
$.createComment(VERSION, { | |
x: 450, | |
y: 400, | |
lifeTime: 0, | |
color: 0xFFFFFF, | |
fontsize: 30, | |
alpha: 1 | |
}); | |
} | |
function drawSongName(x, y, str) { | |
$.createComment(str, { | |
x: x, | |
y: y, | |
lifeTime: 0, | |
color: 0xFFFFFF, | |
fontsize: 36, | |
alpha: 1 | |
}); | |
} | |
//走起! | |
start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment