Skip to content

Instantly share code, notes, and snippets.

@gjz010
Created August 9, 2015 09:26
Show Gist options
  • Save gjz010/2f26fe4c03103dca97a9 to your computer and use it in GitHub Desktop.
Save gjz010/2f26fe4c03103dca97a9 to your computer and use it in GitHub Desktop.
弹幕太鼓 Bilitaiko v0.1
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