这个是一个简单页面游戏,没有使用画布 ,纯靠CSS。整体来说还凑合。属于简单、能用的范畴。代码也很少,就是Sprite和GameScene两个类。
页面测试
function Sprite() {
}
Sprite.prototype = {
config: null,
init: function (v, s) {
this.curr = {};
this.config = v;
this.scene = s;
if (this.config.height) {
} else {
var src = this.config.src_list[0];
var w = src.width / src.cols;
var h = src.height / src.rows;
this.config.height = this.config.width / w * h;
}
},
show: function () {
this.get_div().show();
},
hide: function () {
this.get_div().hide();
},
get_div: function () {
if (this.curr.div)
return this.curr.div;
this.curr.div = $("#div_" + this.config.id);
return this.curr.div;
},
make_html: function (default_pos) {
var html = [];
var id = this.config.id;
var src = this.config.src_list[0];
var w = src.width / src.cols;
var h = src.height / src.rows;
var scal = 100 * src.cols;
var pos = "";
var d = 0;
if (default_pos) {
pos = "left:" + default_pos.x + "rem;top:" + default_pos.y + "rem;"
d = default_pos.d;
}
html.push('<div id="div_' + id + '" class="sprite" style=" ' + pos + ' background-image: url(' + src.src + ') ; background-size: ' + scal + '%; background-position:' + this.get_background_position(src, 0, d) + '; width:' + this.config.width + this.scene.config.size_unit + ';height:' + this.config.height + this.scene.config.size_unit + '" >');
html.push('</div>');
return html.join("");
},
get_background_position: function (src, col, row) {
var w = src.width / src.cols;
var h = src.height / src.rows;
var z = this.scene.config.px_per_rem * this.config.width / w;
var x0 = 0 - w * col * z;
var y0 = 0 - h * row * z;
this.src = src;
this.curr.col = col;
this.curr.row = row;
return x0.toString() + "px " + y0.toString() + "px ";
},
set_pos: function (x, y, d) {
var x_p = x - this.config.width / 2;
var y_p = y - this.config.height;
this.get_div().css({
left: x_p.toString() + this.scene.config.size_unit,
top: y_p.toString() + this.scene.config.size_unit
});
this.curr.row = d;
},
set_pos_center: function (x, y) {
var x_p = x - this.config.width / 2;
var y_p = y - this.config.height / 2;
this.get_div().css({
left: x_p.toString() + this.scene.config.size_unit,
top: y_p.toString() + this.scene.config.size_unit
});
},
set_status: function (status, d) {
for (var i = 0; i < this.config.src_list.length; i++) {
var src = this.config.src_list[i]
if (status == src.group) {
var w = src.width / src.cols;
var h = src.height / src.rows;
this.config.height = this.config.width / w * h;
var s = this.get_background_position(src, 0, d);
this.get_div().css({
"background-image": 'url(' + src.src + ')',
"background-size": 100 * src.cols + '%',
"height": this.config.height + this.scene.config.size_unit,
"background-position": s
});
return;
}
}
},
on_timer: function () {
var i = this.curr.col + 1;
if (i >= this.src.cols)
i = 0;
var row = this.curr.row;
var s = this.get_background_position(this.src, i, row);
this.get_div().css("background-position", s);
}
}
function GameScene() {
}
GameScene.prototype = {
config: null,
sprites: null,
sprite_list: null,
player: null,
target: null,
curr_path: null,
curr_path_step: 0,
curr_path_id: null,
init: function (v) {
this.sprites = {};
this.sprite_list = [];
this.config = v;
this.show_mask();
this.init_map();
this.init_sprite();
this.hide_mask();
this.curr_path_id = 0;
this.sprites["player"].show();
this.set_player_pos(this.config.width / 2, this.config.height / 2, 0)
var that = this;
this.timer = setInterval(function () {
that.on_timer();
}, 140);
if (this.player.config.pos) {
var pos = this.player.config.pos;
this.move_player(pos.x, pos.y, 1, function () {
that.player.set_status("stand", pos.d);
});
}
this.target.set_pos_center(pos.x, pos.y);
},
on_timer: function () {
for (var i = 0; i < this.sprite_list.length; i++) {
this.sprite_list[i].on_timer();
}
//var pos = this.get_player_pos();
//if (pos) {
// var s = pos.x.toFixed(2) + "," + pos.y.toFixed(2);
// $("#div_pos").html(s);
//}
if (div_succ_visbled) {
succ_img_idx = succ_img_idx + 1;
if (succ_img_idx > 9) {
div_succ_visbled = false;
$("#div_succ").hide();
} else {
$("#img_succ").attr("src", "images/game001/UI/a/60-" + succ_img_idx.toString() + ".png");
}
}
},
init_sprite: function () {
var html_player = [];
var html_npc = [];
for (var i = 0; i < this.config.sprite_list.length; i++) {
var rec = this.config.sprite_list[i];
var sprite = new Sprite();
sprite.init(rec, this);
this.sprites[rec.id] = sprite;
if (rec.group == "player") {
html_player.push(sprite.make_html(sprite.config.pos));
}
else {
html_npc.push(sprite.make_html(sprite.config.pos));
}
this.sprites[sprite.config.id] = sprite;
this.sprite_list.push(sprite);
}
$("#" + this.config.div_npc_id).html(html_npc.join(""));
$("#" + this.config.div_player_id).html(html_player.join(""));
this.player = this.sprites["player"];
this.target = this.sprites["target"];
},
init_map: function () {
var w = document.getElementById("div_client").clientWidth;
var h = document.getElementById("div_client").clientHeight;
this.config.px_per_rem = w / this.config.width;
this.config.height = this.config.width / w * h;
this.config.map_height = this.config.map_width / this.config.map_img_width * this.config.map_img_height;
var id = "#" + this.config.img_map_id;
this.map = $(id);
this.map.css("width", this.config.map_width + this.config.size_unit);
this.map.css("height", this.config.map_height + this.config.size_unit);
this.map.css("top", (this.config.height - this.config.map_height) + this.config.size_unit);
this.map.css("left", (this.config.width - this.config.map_width) + this.config.size_unit);
this.map.css("background-image", 'url(' + this.config.map_url + ")");
},
init_player: function () {
this.config.player_height = this.config.player_width / this.config.player_img_width * this.config.player_img_height;
var id = "#" + this.config.img_player_id;
this.player = $(id);
this.player.css("width", this.config.player_width + this.config.size_unit);
this.player.css("height", this.config.player_height + this.config.size_unit);
this.player.css("top", (this.config.height - this.config.player_height) / 2 + this.config.size_unit);
this.player.css("left", (this.config.width - this.config.player_width) / 2 + this.config.size_unit);
this.set_player_status('stop', 0);
},
set_player_pos: function (x, y, d) {
this.player.set_pos(x, y, d);
},
get_d: function (x1, y1, x2, y2) {
var x_inc = Math.abs(x2 - x1);
var y_inc = Math.abs(y2 - y1);
var inc = x_inc;
if (y_inc > inc)
inc = y_inc;
if (y2 < (y1 - inc / 3)) {
if (x2 < (x1 - inc / 3))
return 2;
if (x2 > (x1 + inc / 3))
return 3;
return 6;
} else if (y2 > (y1 + inc / 3)) {
if (x2 < (x1 - inc / 3))
return 1;
if (x2 > (x1 + inc / 3))
return 0;
return 4;
} else {
if (x2 < (x1 - inc / 3))
return 5;
if (x2 > (x1 + inc / 3))
return 7;
return 0;
}
},
game_onmousedown: function (x_client, y_client) {
this.stop_player();
var left = this.px2rem(this.map.css('left'));
var top = this.px2rem(this.map.css('top'));
var x = x_client / this.config.px_per_rem - left;
var y = y_client / this.config.px_per_rem - top;
var p = this.get_player_pos();
var pos1 = { col: Math.round(p.x), row: Math.round(p.y) };
var pos2 = { col: Math.round(x), row: Math.round(y) };
var path = this.get_path(pos1, pos2, this.config.map_data);
//
//this.move_player(x, y, 0, null);
//
this.move_player_path(path, null);
},
move_player_path: function (path, call) {
if (path.length < 2)
return;
this.curr_path = path;
this.curr_path_id = this.curr_path_id + 1;
this.curr_path_step = 1;
if (path.length > 3)
this.curr_path_step = 2;
var p_pos = this.get_player_pos();
var p_target = this.curr_path[this.curr_path.length - 1];
this.target.set_pos_center(p_target.col, p_target.row);
var d = this.get_d(p_pos.x, p_pos.y, p_target.col, p_target.row);
this.player.set_status("run", d);
this.step_player_path();
},
step_player_path: function () {
if (this.curr_path_step >= this.curr_path.length) {
this.player.set_status("stand", this.player.curr.row);
return;
}
var idx = this.curr_path_step;
this.curr_path_step = idx + 1;
var p_pos = this.get_player_pos();
var p_target = this.curr_path[idx];
var d = this.get_d(p_pos.x, p_pos.y, p_target.col, p_target.row);
if (d != this.player.curr.row) {
this.player.set_status("run", d);
}
var that = this;
var x = p_target.col;
var y = p_target.row;
var left = this.px2rem(this.map.css('left')) - (x - p_pos.x);
var top = this.px2rem(this.map.css('top')) - (y - p_pos.y);
this.map.animate({
left: left + this.config.size_unit,
top: top + this.config.size_unit
}, 35, "linear", function () {
that.step_player_path();
});
},
stop_player: function () {
this.map.stop();
this.curr_path = null;
this.player.set_status("stand", this.player.curr.row);
var p_pos = this.get_player_pos();
this.target.set_pos_center(p_pos.x, p_pos.y);
},
move_player: function (x, y, t, call) {
var that = this;
var d = 0;
var p_pos = this.get_player_pos();
d = this.get_d(p_pos.x, p_pos.y, x, y);
var left = this.px2rem(this.map.css('left')) - (x - p_pos.x);
var top = this.px2rem(this.map.css('top')) - (y - p_pos.y);
if (t == 0) {
var l = Math.sqrt(1 + (p_pos.x - x) * (p_pos.x - x) + (p_pos.y - y) * (p_pos.y - y));
t = l * 70 + 350;
}
this.map.stop();
this.target.set_pos_center(x, y);
this.player.set_status("run", d);
this.map.animate({
left: left + this.config.size_unit,
top: top + this.config.size_unit
}, t, function () {
that.player.set_status("stand", d);
if (call) {
call();
}
});
},
px2rem: function (v) {
return parseFloat(v.substr(0, v.length - 2)) / this.config.px_per_rem;
},
get_player_pos: function () {
var left = this.px2rem(this.map.css('left'));
var top = this.px2rem(this.map.css('top'));
var left_p = this.px2rem(this.player.get_div().css('left'));
var top_p = this.px2rem(this.player.get_div().css('top'));
var x = left_p + this.player.config.width / 2 - left;
var y = top_p + this.player.config.height - top;
return { x: x, y: y };
},
show_mask: function () {
$("#" + this.config.div_mask_id).show();
},
hide_mask: function () {
$("#" + this.config.div_mask_id).hide();
},
path
get_v8: function (x_inc, y_inc) {
if (x_inc == 0) {
if (y_inc < 0) {
return [[0, -1], [-1, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, 1]];
} else if (y_inc > 0) {
return [[0, 1], [-1, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [1, -1], [0, -1]];
}
}
if (y_inc == 0) {
if (x_inc < 0) {
return [[-1, 0], [-1, -1], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 1], [1, 0]];
} else if (x_inc > 0) {
return [[1, 0], [1, -1], [1, 1], [0, -1], [0, 1], [-1, -1], [-1, 1], [-1, 0]];
}
}
if ((x_inc == 1) && (y_inc == 1)) {
return [[1, 1], [1, 0], [0, 1], [1, -1], [-1, 1], [0, -1], [-1, 0], [-1, -1]];
}
if ((x_inc == -1) && (y_inc == -1)) {
return [[-1, -1], [-1, 0], [0, -1], [-1, 1], [1, -1], [0, 1], [1, 0], [1, 1]];
}
if ((x_inc == 1) && (y_inc == -1)) {
return [[1, -1], [0, -1], [1, 0], [-1, -1], [1, 1], [-1, 0], [0, 1], [-1, 1]];
}
if ((x_inc == -1) && (y_inc == 1)) {
return [[-1, 1], [0, 1], [-1, 0], [1, 1], [-1, -1], [1, 0], [0, -1], [1, -1]];
}
},
is_line_path: function (path, i1, i2, map_data) {
if (path[i1].col == path[i2].col) {
for (var i = i1; i <= i2; i++) {
if (map_data.data[path[i].row][path[i1].col] < 1)
return false;
}
return true;
}
if (path[i1].row == path[i2].row) {
for (var i = i1; i <= i2; i++) {
if (map_data.data[path[i1].row][path[i].col] < 1)
return false;
}
return true;
}
return false;
},
smooth_path: function (path, map_data) {
for (var k = path.length - 1; k > 0; k--) {
var x2 = path[k].col;
var y2 = path[k].row;
var i_line = -1;
for (var i = k - 1; i >= 0; i--) {
if ((path[i].col == x2) || (path[i].row == y2)) {
if (this.is_line_path(path, i, k, map_data)) {
i_line = i;
}
}
}
if (i_line >= 0) {
if (path[i_line].col == x2) {
for (var i = i_line; i <= k; i++) {
path[i].col = x2;
}
}
if (path[i_line].row == y2) {
for (var i = i_line; i <= k; i++) {
path[i].row = y2;
}
}
}
}
return path;
},
get_path: function (pos1, pos2, map_data) {
var pos_from = pos1;
var pos_to = this.get_pos_canto(pos2, map_data);
var rows = map_data.rows;
var cols = map_data.cols;
if (map_data.pt) {
} else {
map_data.pt = [];
for (var row = 0; row < rows; row++) {
var p = [];
for (var col = 0; col < cols; col++) {
p.push([0, 0]);
}
map_data.pt.push(p);
}
}
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
if (map_data.data[row][col] >= 1) {
map_data.data[row][col] = 1;
}
}
}
var v8 = [[-1, -1], [-1, 0], [-1, 1], [0, 1], [1, 1], [1, 0], [1, -1], [0, -1]];
var v = v8;
var pt = [];
var x_p;
var y_p;
var x;
var y;
var x_inc;
var y_inc;
var xy;
var is_end = false;
var pt_tmp = [];
pt.push(pos_from);
var path = [];
map_data.data[pos_from.row][pos_from.col] = 2;
map_data.pt[pos_from.row][pos_from.col] = [0, 0];
var maxd = Math.sqrt(map_data.cols * map_data.cols + map_data.rows * map_data.rows);
for (var d = 3; d < maxd * 8; d++) {
pt_tmp = [];
for (var i = 0; i < pt.length; i++) {
var x_p = pt[i].col;
var y_p = pt[i].row;
if (x_p <= 0)
continue;
if (x_p >= cols)
continue;
if (y_p <= 0)
continue;
if (y_p >= rows)
continue;
if (d > 3) {
xy = map_data.pt[y_p][x_p];
x_inc = x_p - xy[0];
y_inc = y_p - xy[1];
v = this.get_v8(x_inc, y_inc);
}
for (k = 0; k < v.length; k++) {
x = x_p + v[k][0];
y = y_p + v[k][1];
if ((map_data.data[y][x] == 1)) {
if (map_data.data[y][x] == 1) {
pt_tmp.push({ col: x, row: y });
}
map_data.data[y][x] = d;
map_data.pt[y][x][0] = x_p
map_data.pt[y][x][1] = y_p;
if ((x == pos_to.col) && (y == pos_to.row)) {
var tmp = [];
for (var m = 0; m < d; m++) {
xy = map_data.pt[y][x];
x = xy[0];
y = xy[1];
if ((x > 0) && (y > 0)) {
tmp.push({ col: x, row: y });
}
else {
break;
}
}
path.push(pos_from);
for (var m = tmp.length - 1; m >= 0; m--) {
path.push(tmp[m]);
}
path.push(pos_to);
is_end = true;
break;
}
}
}
if (is_end) {
break;
}
}
if (is_end) {
break;
}
pt = pt_tmp;
}
return this.smooth_path(path, map_data);
},
get_pos_canto: function (pos, map_data) {
if (map_data.data[pos.row][pos.col] >= 1) {
return pos;
}
var x1 = 0;
var x2 = 0;
var y1 = 0;
var y2 = 0;
var maxd = Math.sqrt(map_data.cols * map_data.cols + map_data.rows * map_data.rows);
for (var d = 1; d < maxd; d++) {
x1 = pos.col - d;
x2 = pos.col + d;
y1 = pos.row - d;
y2 = pos.row + d;
if (x1 < 0) x1 = 0;
if (x2 >= map_data.cols) x2 = map_data.cols - 1;
if (y1 < 0) y1 = 0;
if (y2 >= map_data.rows) y2 = map_data.rows - 1;
for (var x = x1; x <= x2; x++) {
if (map_data.data[y1][x] >= 1)
return { col: x, row: y1 }
if (map_data.data[y2][x] >= 1)
return { col: x, row: y2 }
}
for (var y = y1; y <= y2; y++) {
if (map_data.data[y][x1] >= 1)
return { col: x1, row: y }
if (map_data.data[y][x2] >= 1)
return { col: x2, row: y }
}
}
return null;
}
}