346 lines
7.7 KiB
JavaScript
346 lines
7.7 KiB
JavaScript
/* Arkanoid level is 10x10 */
|
|
var score = 0;
|
|
var highscore = 0;
|
|
var lives = 3;
|
|
|
|
var brick = World.spawn(gameobjects['brick']);
|
|
var brickbb = brick.char.boundingbox;
|
|
var bwidth = brickbb.r - brickbb.l;
|
|
var bheight = brickbb.t-brickbb.b;
|
|
brick.kill();
|
|
|
|
var rows = 15;
|
|
var cols = 13;
|
|
|
|
var lvlwidth = bwidth*cols;
|
|
var lvlheight = 600;
|
|
|
|
//var frameworld = World
|
|
|
|
var f = World.spawn(gameobjects['edge2d']);
|
|
f.edge2d.thickness = 10;
|
|
f.edge2d.cpoints = Geometry.box(lvlwidth+f.edge2d.thickness*2,lvlheight);
|
|
f.draw = function() {
|
|
Debug.line(f.edge2d.points, Color.green, 0, f.edge2d.thickness*2);
|
|
};
|
|
|
|
Register.draw.register(f.draw,f);
|
|
|
|
var fitbricks = Math.floor(lvlwidth/bwidth);
|
|
|
|
var wingame = function() {
|
|
allballs.forEach(x=>x.kill());
|
|
Log.warn("WINNER");
|
|
Player.players[0].uncontrol(paddle);
|
|
|
|
Register.gui.register(function() {
|
|
GUI.text("WINNER", Window.dimensions.scale(0.5));
|
|
});
|
|
}
|
|
|
|
/* Spawn bricks */
|
|
if (!IO.exists('lvl1.json')) {
|
|
var lvl1 = {};
|
|
lvl1.bricks = [];
|
|
|
|
for (var i = 0; i < rows; i++) {
|
|
lvl1.bricks.push([]);
|
|
for (var j = 0; j < cols; j++) {
|
|
lvl1.bricks[i].push(1);
|
|
}
|
|
}
|
|
|
|
IO.slurpwrite(JSON.stringify(lvl1), 'lvl1.json');
|
|
}
|
|
|
|
Color.Arkanoid = {
|
|
white: [0,0,0,255],
|
|
orange: [255,143,0,255],
|
|
teal: [0,255,255,255],
|
|
green: [0,255,0,255],
|
|
red: [255,0,0,255],
|
|
blue: [0,112,255,255],
|
|
purple: [255,0,255,255],
|
|
yellow: [255,255,0],
|
|
silver: [157,157,157],
|
|
gold: [188,174,0],
|
|
};
|
|
|
|
Color.Arkanoid.Powerups = {
|
|
red: [174,0,0], /* laser */
|
|
blue: [0,0,174], /* enlarge */
|
|
green: [0,174,0], /* catch */
|
|
orange: [224,143,0], /* slow */
|
|
purple: [210,0,210], /* break */
|
|
cyan: [0,174,255], /* disruption */
|
|
gray: [143,143,143] /* 1up */
|
|
};
|
|
|
|
var lvl = JSON.parse(IO.slurp("lvl1.json"));
|
|
|
|
for (var row = 0; row < rows; row++) {
|
|
for (var col = 0; col < cols; col++) {
|
|
if (lvl.bricks[row][col] === 0)
|
|
continue;
|
|
|
|
var brick = World.spawn(gameobjects['brick']);
|
|
brick.powerup = function() {
|
|
if (Math.random() < 0.1)
|
|
spawn_random_powerup(this.pos);
|
|
|
|
if (this.instances === 1)
|
|
wingame();
|
|
};
|
|
|
|
// brick.char.color = bcolor;
|
|
var startrow = lvlheight/2-bheight*2; // one brick gap between top and brick start
|
|
var x = -(cols/2) * bwidth;
|
|
var pos = [x+bwidth*col+bwidth/2, startrow-bheight*row];
|
|
brick.pos = pos;
|
|
}
|
|
}
|
|
|
|
var flashtimer = timer.make(function() {
|
|
if (gameobjects['brick'].instances.length === 0) {
|
|
flashtimer.kill();
|
|
return;
|
|
}
|
|
var idx = Math.randomint(gameobjects['brick'].instances.length);
|
|
gameobjects['brick'].instances[idx].flash();
|
|
flashtimer.time = Math.random_range(1,3);
|
|
}, Math.random_range(1,3));
|
|
|
|
var paddle = World.spawn(gameobjects['paddle']);
|
|
paddle.extents = lvlwidth/2 - f.edge2d.thickness;
|
|
paddle.pos = [0,-lvlheight/2+paddle.height*4];
|
|
paddle.setgrow(3);
|
|
paddle.lasership();
|
|
|
|
Gamestate.spawnball = function() {
|
|
var bb = World.spawn(gameobjects['ball']);
|
|
bb.pos = bb.pos.add([0,-200]);
|
|
bb.velocity = [30,200];
|
|
bb.draw_layer = 3;
|
|
bb.tag = 'ball';
|
|
}
|
|
|
|
var powerups = {};
|
|
|
|
function mk_pup(color, fn, weight) {
|
|
weight ??= 1;
|
|
var o = {};
|
|
o.color = color;
|
|
o.fn = fn;
|
|
o.weight = weight;
|
|
return o;
|
|
};
|
|
|
|
powerups.laser = mk_pup(Color.Arkanoid.Powerups.red, function() {
|
|
paddle.lasership();
|
|
});
|
|
powerups.enlarge = mk_pup(Color.Arkanoid.Powerups.blue, function() { paddle.grow(); });
|
|
powerups.catch = mk_pup(Color.Arkanoid.Powerups.green, function() {
|
|
paddle.sticky = true;
|
|
});
|
|
powerups.slow = mk_pup(Color.Arkanoid.Powerups.orange, function() {
|
|
/* Slow all balls */
|
|
gameobjects['ball'].instances.forEach(function(x) {
|
|
x.velocity = x.velocity.scale(0.5);
|
|
});
|
|
});
|
|
powerups.break = mk_pup(Color.Arkanoid.Powerups.purple, function() {
|
|
clear_level();
|
|
}, 0.5);
|
|
powerups.disruption = mk_pup(Color.Arkanoid.Powerups.cyan, function() {
|
|
var ball = gameobjects['ball'].instances[0];
|
|
if (!ball) return;
|
|
|
|
ball.instandup();
|
|
ball.instandup();
|
|
});
|
|
powerups.player = mk_pup(Color.Arkanoid.Powerups.gray, function() {
|
|
lives += 1;
|
|
}, 0.5);
|
|
|
|
function select_weighted(objs)
|
|
{
|
|
var total = 0;
|
|
var total = objs.reduce(function(acc, item) { acc += item.weight; return acc; }, 0);
|
|
var selection = Math.random() * total;
|
|
|
|
var i;
|
|
for (i = 0; i < objs.length-1; i++) {
|
|
selection -= objs[i].weight;
|
|
if (selection <= 0)
|
|
return objs[i];
|
|
};
|
|
|
|
return objs.last;
|
|
}
|
|
|
|
function select_weighted_binary(objs)
|
|
{
|
|
var mobjs = objs.slice();
|
|
mobjs[0].total = 0;
|
|
for (var i = 1; i < mobjs.length; i++)
|
|
mobjs[i].total = mobjs[i-1].total + mobjs[i].weight;
|
|
|
|
var select = Math.random() * mobjs.last.total
|
|
var obj = Math.floor((mobjs.length-1)/2);
|
|
|
|
while (mobjs.length > 0) {
|
|
if (select < mobjs[obj].total) {
|
|
mobjs.splice(obj,obj-1);
|
|
obj = Math.floor((mobjs.length-1)/2);
|
|
} else if (select > mobjs[obj+1].total) {
|
|
mobjs.splice(0,obj-1);
|
|
obj = Math.floor((mobjs.length-1)/2);
|
|
} else
|
|
return mobjs[obj];
|
|
}
|
|
|
|
return mobjs[obj];
|
|
}
|
|
|
|
var last_powerup = {};
|
|
|
|
function spawn_random_powerup(pos)
|
|
{
|
|
if (gameobjects['upgrade_drop'].instances.length !== 0) return;
|
|
var p = World.spawn(gameobjects['upgrade_drop']);
|
|
p.pos = pos;
|
|
|
|
var power = select_weighted(powerups.array());
|
|
if (last_powerup === power)
|
|
power = powerups.disruption;
|
|
|
|
last_powerup = power;
|
|
|
|
p.color = power.color;
|
|
p.upgrade = power.fn;
|
|
}
|
|
|
|
function spawn_powerup(pos, fn) {
|
|
var p = World.spawn(gameobjects['upgrade_drop']);
|
|
p.pos = pos;
|
|
p.upgrade = fn;
|
|
return p;
|
|
}
|
|
|
|
function multiball(n) {
|
|
for (var i = 0; i < n; i++)
|
|
Gamestate.spawnball();
|
|
}
|
|
|
|
function lostball()
|
|
{
|
|
if (gameobjects['ball'].instances.length === 0)
|
|
lostlife();
|
|
};
|
|
|
|
function lostgame()
|
|
{
|
|
Log.warn("LOSER");
|
|
backtomain();
|
|
}
|
|
|
|
function lostlife() {
|
|
lives--;
|
|
|
|
if (lives === 0)
|
|
lostgame();
|
|
else
|
|
Gamestate.spawnball();
|
|
};
|
|
|
|
Gamestate.spawnball();
|
|
var killbox = World.spawn(gameobjects['polygon2d']);
|
|
|
|
killbox.polygon2d.points = Geometry.box(lvlwidth,30);
|
|
killbox.pos = [0,-lvlheight/2];
|
|
killbox.polygon2d.sensor = true;
|
|
killbox.register_hit(hit => {
|
|
if (hit.obj.tag === 'ball') {
|
|
hit.obj.kill();
|
|
lostball();
|
|
}
|
|
|
|
}, killbox);
|
|
|
|
//Sound.play("start.wav");
|
|
|
|
var pause = {
|
|
gui() {
|
|
var pausecolor = [0,0,0,100];
|
|
Debug.box(Window.dimensions.scale(0.5), Window.dimensions, pausecolor);
|
|
GUI.text_fn("PAUSE", {font_size: 3, anchor: [0.5,0.5]}).draw(Window.dimensions.scale([0.5,0.5]));
|
|
},
|
|
|
|
unpause() {
|
|
Register.gui.unregister(pause.gui);
|
|
sim_start();
|
|
},
|
|
|
|
input_escape_pressed() {
|
|
pause.unpause();
|
|
Player.players[0].control(gamepawn);
|
|
},
|
|
};
|
|
|
|
|
|
var gamepawn =
|
|
{
|
|
pause() {
|
|
Register.gui.register(pause.gui);
|
|
sim_pause();
|
|
},
|
|
|
|
input_escape_pressed() {
|
|
backtomain();
|
|
return;
|
|
this.pause();
|
|
Player.players[0].uncontrol(gamepawn);
|
|
Player.players[0].control(pause);
|
|
},
|
|
|
|
input_o_pressed() {
|
|
clear_level();
|
|
},
|
|
}
|
|
|
|
function clear_level() {
|
|
var bricks = gameobjects['brick'].instances.slice();
|
|
bricks.forEach(function(x) { x.kill(); });
|
|
};
|
|
|
|
function gamegui() {
|
|
GUI.column({
|
|
items: [
|
|
GUI.text_fn("SCORE", {color: Color.red}),
|
|
GUI.text_fn(`${score}`),
|
|
GUI.text_fn("HIGH SCORE", {color: Color.red}),
|
|
GUI.text_fn(`${highscore}`),
|
|
GUI.text_fn(`BRICKS: ${gameobjects['brick'].instances.length}`),
|
|
GUI.text_fn(`BALLS IN PLAY: ${gameobjects['ball'].instances.length}`),
|
|
|
|
GUI.text_fn(`LIVES: ${lives}`),
|
|
GUI.text_fn("YARKANOID", {color: [5,120,240,255]}),
|
|
|
|
GUI.text_fn("ODPLOT GAMES"),
|
|
GUI.text_fn("[C] 2023"),
|
|
]
|
|
}).draw(Window.dimensions.scale([0.8,0.8]));
|
|
}
|
|
|
|
Register.gui.register(gamegui);
|
|
|
|
Player.players[0].control(gamepawn);
|
|
|
|
let backtomain = function()
|
|
{
|
|
World.clear();
|
|
run("startmenu.js");
|
|
Register.gui.unregister(gamegui);
|
|
Player.players[0].uncontrol(gamepawn);
|
|
}
|