Files
mixly3/boards/default/python_skulpt_car/bg_highlight_f8cee65f.js
2025-11-06 18:43:47 +08:00

1355 lines
62 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//这一版加入了所有延时和高亮效果,用以适应分布调试
var $builtinmodule = function (name) {
let mod= {__name__: new Sk.builtin.str("blocklygame")};
var svg = d3.select(Sk.TurtleGraphics.target).append('svg');
//其他变量设置
var map=//迷宫布局
[[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 2, 1, 1, 1, 1, 3, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
var DirectionType={//移动方向的类型
NORTH: 0,
EAST: 1,
SOUTH: 2,
WEST: 3
}
var ResultType = {
UNSET: 0,
SUCCESS: 1,
FAILURE: -1,
TIMEOUT: 2,
ERROR: -2
}
var tile_SHAPES = {
'10010': [4, 0], // Dead ends
'10001': [3, 3],
'11000': [0, 1],
'10100': [0, 2],
'11010': [4, 1], // Vertical
'10101': [3, 2], // Horizontal
'10110': [0, 0], // Elbows
'10011': [2, 0],
'11001': [4, 2],
'11100': [2, 3],
'11110': [1, 1], // Junctions
'10111': [1, 0],
'11011': [2, 1],
'11101': [1, 2],
'11111': [2, 2], // Cross
'null0': [4, 3], // Empty
'null1': [3, 0],
'null2': [3, 1],
'null3': [0, 3],
'null4': [1, 3]
}
// 角色变量
var actor={
img : "../common/js/skulpt_mixcar/pic/pegman.png",
height : 52,
width : 49,
direction : DirectionType.EAST,
type:"animate",
x : 0,
y : 0,
stepSpeed : 150,
coin_point:0,
marker_num:0,
oil:1,//表示小车有充足的油量(为了适应教材而新增的变量)
traffic_light:22,//表示红绿灯为绿灯
circulation_num:0,//小车在赛道中循环的次数
invisible_mark:0//在地图中不可显示的标记数目用于检测小车是否沿着特定路线走。规定不可见的标记点INVIMAKER=24
};
//迷宫变量
var maze_SQUARE_SIZE = 50;
var maze_ROWS=map.length;
var maze_COLS=map[0].length;
var maze_marker_num=0;//迷宫中标记点的数目
var maze={
mlevel:0,
tiles: '../common/js/skulpt_mixcar/pic/maze_path.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/marker.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg_astro.jpg',//地图背景图片
wall:'../common/js/skulpt_mixcar/pic/roadblock.png',
award:'../common/js/skulpt_mixcar/pic/award.png',
barrier:'',
markers:[],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
START: 2,
FINISH: 3,
AWARD:4,//金币奖励
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * maze_COLS,
MAZE_HEIGHT : maze_SQUARE_SIZE * maze_ROWS,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:1,//类型为用户自定义的
INVIMNUM : 0
};
//已经设置好的关卡的map
var MAZE_setted=[
//第一关
{ mlevel:1,
map:[
[0, 1, 1, 13, 1, 1, 12, 0],
[0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 9, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 10, 1, 1, 11, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg1.jpg',//地图背景图片
wall:'',
award:'',
barrier:'',
markers:['../common/js/skulpt_mixcar/pic/red.png','../common/js/skulpt_mixcar/pic/yellow.png','../common/js/skulpt_mixcar/pic/blue.png','../common/js/skulpt_mixcar/pic/green.png'],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
MARKER1:10,
MARKER2:11,
MARKER3:12,
MARKER4:13,
S_F: 9,//既是起点又是终点
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:0,//类型为非用户自定义的
INVIMNUM : 0
},
//第二关
{
mlevel:2,
map:[
[0, 1, 1, 13, 1, 1, 12, 0],
[0, 1, 0, 5, 0, 0, 1, 0],
[0, 1, 1, 9, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 10, 1, 1, 11, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg2.jpg',//地图背景图片
wall:'',
award:'',
barrier:'../common/js/skulpt_mixcar/pic/barrier.png',
markers:['../common/js/skulpt_mixcar/pic/red.png','../common/js/skulpt_mixcar/pic/yellow.png','../common/js/skulpt_mixcar/pic/blue.png','../common/js/skulpt_mixcar/pic/green.png'],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
BARRIER:5,
MARKER1:10,
MARKER2:11,
MARKER3:12,
MARKER4:13,
S_F: 9,//既是起点又是终点
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:0,//类型为非用户自定义的
INVIMNUM : 0
},
//第三关
{ mlevel:3,
map:[
[0, 1, 1, 13, 24, 1, 24, 0],
[0, 1, 0, Math.random()>0.5?1:5, 0, 0, 1, 0],
[0, 1, 1, 9, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 24, 1, 1, 24, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg2.jpg',//地图背景图片
wall:'',
award:'',
barrier:'../common/js/skulpt_mixcar/pic/barrier.png',
markers:['../common/js/skulpt_mixcar/pic/red.png','../common/js/skulpt_mixcar/pic/yellow.png','../common/js/skulpt_mixcar/pic/blue.png','../common/js/skulpt_mixcar/pic/green.png'],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
BARRIER:5,
MARKER4:13,
S_F: 9,//既是起点又是终点
INVIMAKER: 24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:0,//类型为非用户自定义的
INVIMNUM : 4
},
//第四关
{ mlevel:4,
map:[
[0, 1, 1, 13, 24, 1, 24, 0],
[20, 1, 0, Math.random()>0.5?1:5, 0, 0, 1, 0],
[0, 1, 1, 9, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 24, 1, 1, 24, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg3.jpg',//地图背景图片
wall:'',
award:'',
barrier:'../common/js/skulpt_mixcar/pic/barrier.png',
markers:['../common/js/skulpt_mixcar/pic/red.png','../common/js/skulpt_mixcar/pic/yellow.png','../common/js/skulpt_mixcar/pic/blue.png','../common/js/skulpt_mixcar/pic/green.png'],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
BARRIER:5,
MARKER4:13,
S_F: 9,//既是起点又是终点
OIL_STATION:20,//加油站
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:0,//类型为非用户自定义的
INVIMNUM : 4
},
//第五关
{ mlevel:5,
map:[
[0, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 2, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg1.jpg',//地图背景图片
wall:'',
award:'',
barrier:'',
markers:[],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
START: 2,
S_F: 9,//既是起点又是终点
TRAFFIC_LIGHT:21,//红绿灯
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:3,y:2},
type:0,//类型为非用户自定义的
INVIMNUM : 0
},
//第六关
{ mlevel:6,
map:[
[0, 1, 1, 13, 1, 1, 12, 0],
[0, 1, 0, 1, 0, 0, 1, 0],
[0, 1, 1, 2, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 10, 1, 1, 11, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg1.jpg',//地图背景图片
wall:'',
award:'',
barrier:'',
markers:['../common/js/skulpt_mixcar/pic/red.png','../common/js/skulpt_mixcar/pic/yellow.png','../common/js/skulpt_mixcar/pic/blue.png','../common/js/skulpt_mixcar/pic/green.png'],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
START: 2,
MARKER1:10,
MARKER2:11,
MARKER3:12,
MARKER4:13,
S_F: 9,//既是起点又是终点
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:0,y:0},
type:0,//类型为非用户自定义的
INVIMNUM : 0
},
//第七关
{ mlevel:7,
map:[
[0, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 2, 22, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0]],
tiles: '../common/js/skulpt_mixcar/pic/tiles_road.png',//地图路径图片
marker: '../common/js/skulpt_mixcar/pic/Start_final.png',//终点图标图片
background: '../common/js/skulpt_mixcar/pic/bg4.jpg',//地图背景图片
wall:'',
award:'',
barrier:'',
markers:[],
SquareType :{//迷宫中方块的类型
WALL: 0,
OPEN: 1,
START: 2,
S_F: 9,//既是起点又是终点
LIGHT_GREEN:22,//红绿灯中的绿灯
LIGHT_RED:23,//红绿灯中的红灯
INVIMAKER:24
},
//迷宫部分参数指定
MAZE_WIDTH : maze_SQUARE_SIZE * 8,
MAZE_HEIGHT : maze_SQUARE_SIZE * 8,
PATH_WIDTH : maze_SQUARE_SIZE / 3,
result : ResultType.UNSET,
finish : {x:3,y:2},
type:0,//类型为非用户自定义的
INVIMNUM : 0
}
]
/**
* Display Pegman at the specified location, facing the specified direction.
* @param {number} x Horizontal grid (or fraction thereof).
* @param {number} y Vertical grid (or fraction thereof).
* @param {number} d Direction (0 - 15) or dance (16 - 17).
* @param {number=} opt_angle Optional angle (in degrees) to rotate Pegman.
*/
var displayPegman = function(x, y, d, opt_angle) {
var pegmanIcon = $(Sk.TurtleGraphics.target).find('#pegman');
if(actor.type=='animate'){
if(maze.type==0){
pegmanIcon.attr('x', x * maze_SQUARE_SIZE - d * actor.width+ 1);
pegmanIcon.attr('y', maze_SQUARE_SIZE * (y + 0.5) - actor.height / 2 );
}else{
pegmanIcon.attr('x', x * maze_SQUARE_SIZE - d * actor.width + 1);
pegmanIcon.attr('y', maze_SQUARE_SIZE * (y + 0.5) - actor.height / 2 - 8);
}
if (opt_angle) {
pegmanIcon.attr('transform', 'rotate(' + opt_angle + ', ' +
(x * maze_SQUARE_SIZE + maze_SQUARE_SIZE / 2) + ', ' +
(y * maze_SQUARE_SIZE + maze_SQUARE_SIZE / 2) + ')');
} else {
pegmanIcon.attr('transform', 'rotate(0, 0, 0)');
}
}else{
pegmanIcon.attr('x', x * maze_SQUARE_SIZE + 1);
pegmanIcon.attr('y', maze_SQUARE_SIZE * (y + 0.5) - actor.height / 2 );
}
var clipRect = $(Sk.TurtleGraphics.target).find('#clipRect');
clipRect.attr('x', x * maze_SQUARE_SIZE + 1);
clipRect.attr('y', pegmanIcon.attr('y'));
};
var initPegman=function(){
// Pegman's clipPath element, whose (x, y) is reset by Maze.displayPegman
svg.append('clipPath').attr('id','pegmanClipPath')
const elem = Sk.TurtleGraphics.target.querySelector("#pegmanClipPath");
d3.select(elem).append('rect').attr('id','clipRect').attr('width', actor.width).attr('height', actor.height)
if(actor.type=="animate"){
if(maze.type==0){
//绘制精灵.
svg.append('image').attr('id','pegman').attr('width', actor.width * 16).attr('height', actor.height).attr('clip-path', 'url(#pegmanClipPath)')
.attr('xlink:href',actor.img)
}else{
//绘制精灵.
svg.append('image').attr('id','pegman').attr('width', actor.width * 21).attr('height', actor.height).attr('clip-path', 'url(#pegmanClipPath)')
.attr('xlink:href',actor.img)
}
}else{
//绘制精灵.
svg.append('image').attr('id','pegman').attr('width', actor.width ).attr('height', actor.height).attr('clip-path', 'url(#pegmanClipPath)')
.attr('xlink:href',actor.img)
}
displayPegman(actor.x , actor.y , actor.direction*4 )
}
var drawMap=function(){
svg.attr('id','game_stage')
var scale = Math.max(maze_ROWS, maze_COLS) * maze_SQUARE_SIZE;
svg.attr('viewBox', '0 -10 ' + scale + ' ' + (scale+10));
// 绘制外框
svg.append('rect').attr('x', 0).attr('y', 0).attr('width', maze.MAZE_WIDTH).attr('height', maze.MAZE_HEIGHT)
.style('fill','#F1EEE7').style('stroke','#CCB').style('stroke-width','1');
// for (var y = 0; y < maze_ROWS; y++) {
// for (var x = 0; x < maze_COLS; x++) {
// //绘制迷宫背景
// svg.append('image').attr('x', x*maze_SQUARE_SIZE).attr('y', y*maze_SQUARE_SIZE).attr('width', maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
// .attr('xlink:href',maze.background)
// }
// }
svg.append('image').attr('x', 0).attr('y', 0).attr('width', maze_SQUARE_SIZE*maze_COLS).attr('height',maze_SQUARE_SIZE*maze_ROWS)
.attr('xlink:href',maze.background)
//初始化地图
var normalize = function(x, y) {
if (x < 0 || x >= maze_COLS || y < 0 || y >= maze_ROWS) {
return '0';
}
return ((map[y][x] == maze.SquareType.WALL)||(map[y][x] == maze.SquareType.OIL_STATION)) ? '0' : '1';
};
// 依次判断格子的类型,并绘制相应格子内的图形
var tileId = 0;
for (var y = 0; y < maze_ROWS; y++) {
for (var x = 0; x < maze_COLS; x++) {
// 标记每个格子的“弯曲状态”.
var tileShape = normalize(x, y) +
normalize(x, y - 1) + // North.
normalize(x + 1, y) + // West.
normalize(x, y + 1) + // South.
normalize(x - 1, y); // East.
// 绘制路径.
if (!tile_SHAPES[tileShape]) {
// Empty square. Use null0 for large areas, with null1-4 for borders.
// Add some randomness to avoid large empty spaces.
if (tileShape == '00000' && Math.random() > 0.3) {
tileShape = 'null0';
} else {
tileShape = 'null' + Math.floor(1 + Math.random() * 4);
}
}
var left = tile_SHAPES[tileShape][0];
var top = tile_SHAPES[tileShape][1];
// Tile's clipPath element.
svg.append('clipPath').attr('id','tileClipPath' + tileId)
const elem = Sk.TurtleGraphics.target.querySelector("#tileClipPath" + tileId);
d3.select(elem).append('rect').attr('x', x * maze_SQUARE_SIZE).attr('y', y * maze_SQUARE_SIZE).attr('width', maze_SQUARE_SIZE).attr('height', maze_SQUARE_SIZE)
if(maze.type==0){//非用户自定义
// Tile sprite.
if ((map[y][x] != maze.SquareType.WALL) && (map[y][x] != maze.SquareType.OIL_STATION) && (map[y][x] != maze.SquareType.TRAFFIC_LIGHT)&& (map[y][x] != maze.SquareType.LIGHT_GREEN)&& (map[y][x] != maze.SquareType.LIGHT_RED)) {
svg.append('image').attr('x', x * maze_SQUARE_SIZE).attr('y', y * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE ).attr('height',maze_SQUARE_SIZE )
.attr('clip-path', 'url(#tileClipPath' + tileId + ')').attr('xlink:href',maze.tiles);
tileId++;
}
}else{
// Tile sprite.
svg.append('image').attr('x',(x - left) * maze_SQUARE_SIZE).attr('y',(y - top) * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE * 5).attr('height',maze_SQUARE_SIZE * 4)
.attr('clip-path', 'url(#tileClipPath' + tileId + ')').attr('xlink:href',maze.tiles)
tileId++;
}
if(map[y][x]==0){//当地图中此处标记为墙时
svg.append('image').attr('x',x * maze_SQUARE_SIZE + (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.8/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.8/2)).attr('width',maze_SQUARE_SIZE*0.8 ).attr('height',maze_SQUARE_SIZE*0.8)
.attr('xlink:href',maze.wall)
}else if(map[y][x]==4){//当地图中此处标记为金币时
svg.append('image').attr('id','coin'+y+x).attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.5/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.5/2)).attr('width',maze_SQUARE_SIZE*0.5).attr('height',maze_SQUARE_SIZE*0.5)
.attr('xlink:href',maze.award)
}else if(map[y][x]==5){//当地图中此处标记为障碍时
svg.append('image').attr('id','barrier'+y+x).attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href',maze.barrier)
}else if(map[y][x]==10){//当地图中此处标记为符号1——红标时
svg.append('image').attr('id','marker1').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href',maze.markers[0])
maze_marker_num+=1
}else if(map[y][x]==11){//当地图中此处标记为符号2——橘标时
svg.append('image').attr('id','marker2').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href',maze.markers[1])
maze_marker_num+=1
}else if(map[y][x]==12){//当地图中此处标记为符号3——蓝标时
svg.append('image').attr('id','marker3').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href',maze.markers[2])
maze_marker_num+=1
}else if(map[y][x]==13){//当地图中此处标记为符号4——绿标时
svg.append('image').attr('id','marker4').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href',maze.markers[3])
maze_marker_num+=1
}
}
}
if(maze.type==1){
// 绘制终点图标
svg.append('image').attr('id','finish').attr('width', 0.5 * maze_SQUARE_SIZE).attr('height', 0.5*maze_SQUARE_SIZE).attr('xlink:href',maze.marker)
//定位:精灵与终点初始的位置
// Locate the start and finish squares.
for (var y = 0; y < maze_ROWS; y++) {
for (var x = 0; x < maze_COLS; x++) {
if (map[y][x] == maze.SquareType.START) {
actor.x= x;
actor.y= y;
} else if (map[y][x] == maze.SquareType.FINISH) {
// Move the finish icon into position.
var finishIcon = $(Sk.TurtleGraphics.target).find('#finish');
finishIcon.attr('x', maze_SQUARE_SIZE * (x + 0.5) -
finishIcon.attr('width') / 2);
finishIcon.attr('y', maze_SQUARE_SIZE * (y + 0.6) -
finishIcon.attr('height'));
maze.finish={x:x,y:y}
}
}
}
}else{
//绘制既是起点、又是终点的坐标
// Locate the start and finish squares.
for (var y = 0; y < maze_ROWS; y++) {
for (var x = 0; x < maze_COLS; x++) {
if (map[y][x] == 9) {//既是起点又是终点
// 绘制终点图标
svg.append('image').attr('id','finish').attr('width', maze_SQUARE_SIZE*0.8).attr('height', maze_SQUARE_SIZE*0.8).attr('xlink:href',maze.marker)
actor.x= x;
actor.y= y;
var finishIcon = $(Sk.TurtleGraphics.target).find('#finish');
finishIcon.attr('x', maze_SQUARE_SIZE * x+5 );
finishIcon.attr('y', maze_SQUARE_SIZE * y+5);
maze.finish={x:x,y:y}
}else if(map[y][x]==20){//当地图中此处标记为20——加油站时
svg.append('image').attr('id','station').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.8/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.8/2)).attr('width',maze_SQUARE_SIZE*2*0.8).attr('height',maze_SQUARE_SIZE*0.8)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/oilstation.png')
}else if(map[y][x]==21){//当地图中此处标记为21——红绿灯时
svg.append('image').attr('id','trafficlight').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/trafficlight.png')
}else if(map[y][x]==22){//当地图中此处标记为22——红绿灯中的绿灯时
svg.append('image').attr('id','lightgreen').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/greenlight.png')
}else if(map[y][x]==23){//当地图中此处标记为23——红绿灯中的红灯时
svg.append('image').attr('id','lightred').attr('x',x * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('y',y * maze_SQUARE_SIZE+ (maze_SQUARE_SIZE/2 - maze_SQUARE_SIZE*0.7/2)).attr('width',maze_SQUARE_SIZE*0.7).attr('height',maze_SQUARE_SIZE*0.7)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/redlight.png')
}else if(map[y][x]==2){//当地图中此处标记为起点时,画上和“既是起点又是终点”一样的图标
actor.x= x;
actor.y= y;
svg.append('image').attr('id','start').attr('x', maze_SQUARE_SIZE * x).attr('y',maze_SQUARE_SIZE * y+5).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE*0.8)
.attr('xlink:href',maze.marker)
}
}
}
}
}
//检查是否已到终点
var checkFinish=function(){
maze.result = actor.x != maze.finish.x || actor.y != maze.finish.y ?
ResultType.UNSET : ResultType.SUCCESS;
if(maze.result==ResultType.SUCCESS){
if(maze.type==1){
return true
}else{
if(maze.mlevel==5 || maze.mlevel==7 ||maze.mlevel==6){
return true
}else{
if(actor.marker_num==maze_marker_num){
if(actor.invisible_mark>=maze.INVIMNUM){
return true
}else{return "error3"}
}else{return "error2"}
}
}
}else{
return false
}
}
/**
* Is there a path next to pegman?
* @param {number} direction Direction to look
* (0 = forward, 1 = right, 2 = backward, 3 = left).
* @param {?string} id ID of block that triggered this action.
* Null if called as a helper function in Maze.move().
* @return {boolean} True if there is a path.
*/
var isPath=function(direction,id){
var effectiveDirection = actor.direction + direction;
var square;
var command;
switch (constrainDirection4(effectiveDirection)) {
case DirectionType.NORTH:
square = map[actor.y - 1] && map[actor.y - 1][actor.x];
command = 'look_north';
break;
case DirectionType.EAST:
square = map[actor.y][actor.x + 1];
command = 'look_east';
break;
case DirectionType.SOUTH:
square = map[actor.y + 1] && map[actor.y + 1][actor.x];
command = 'look_south';
break;
case DirectionType.WEST:
square = map[actor.y][actor.x - 1];
command = 'look_west';
break;
}
if (id) {
return [command , square !== maze.SquareType.WALL && square !== undefined && square !== maze.SquareType.BARRIER && square !== maze.SquareType.OIL_STATION && square !== maze.SquareType.TRAFFIC_LIGHT && square !== maze.SquareType.LIGHT_RED && square !== maze.SquareType.LIGHT_GREEN]
}
return square !== maze.SquareType.WALL && square !== undefined && square !== maze.SquareType.BARRIER && square !== maze.SquareType.OIL_STATION && square !== maze.SquareType.TRAFFIC_LIGHT && square !== maze.SquareType.LIGHT_RED && square !== maze.SquareType.LIGHT_GREEN;
};
var constrainDirection4 = function(d) {
d = Math.round(d) % 4;
if (d < 0) {
d += 4;
}
return d;
};
var constrainDirection16 = function(d) {
d = Math.round(d) % 16;
if (d < 0) {
d += 16;
}
return d;
};
/**
* Attempt to move pegman forward or backward.
* @param {number} direction Direction to move .
* @param {string} id ID of block that triggered this action.
* @throws {true} If the end of the maze is reached.
* @throws {false} If Pegman collides with a wall.
*/
var move = function(direction) {
if (!isPath(0, null)) {
return false
}
var command;
switch (constrainDirection4(direction)) {
case DirectionType.NORTH:
command = 'north';
break;
case DirectionType.EAST:
command = 'east';
break;
case DirectionType.SOUTH:
command = 'south';
break;
case DirectionType.WEST:
command = 'west';
break;
}
return command
};
/**
* Turn pegman left or right.
* @param {number} direction Direction to turn (0 = left, 1 = right).
* @param {string} id ID of block that triggered this action.
*/
var turn = function(direction) {
var command;
if (direction=='right') {
// Right turn (clockwise).
command='right'
} else {
// Left turn (counterclockwise).
command='left'
}
return command
};
/**
* Schedule the animations for a move or turn.
* @param {!Array.<number>} startPos X, Y starting points.
* @param {!Array.<number>} endPos X, Y ending points.
*/
var schedule = function(startPos, endPos) {
var deltas = [(endPos[0] - startPos[0]) / 4, (endPos[1] - startPos[1]) / 4, (endPos[2] - startPos[2]) / 4];
displayPegman(startPos[0] + deltas[0], startPos[1] + deltas[1], constrainDirection16(startPos[2] + deltas[2]));
setTimeout(function() {
displayPegman(startPos[0] + deltas[0] * 2, startPos[1] + deltas[1] * 2, constrainDirection16(startPos[2] + deltas[2] * 2));
}, actor.stepSpeed);
setTimeout(function() {
displayPegman(startPos[0] + deltas[0] * 3, startPos[1] + deltas[1] * 3, constrainDirection16(startPos[2] + deltas[2] * 3));
}, actor.stepSpeed * 2)
setTimeout(function() {
displayPegman(endPos[0], endPos[1], constrainDirection16(endPos[2]));
}, actor.stepSpeed * 3)
};
/**
* 检查精灵在移动的过程中是否吃到了金币
* @param {<number>} x 当前精灵的横坐标.
* @param {<number>} y 当前精灵的纵坐标.
*/
var hasCoin=function(x , y) {
if(map[y][x]==maze.SquareType.AWARD){//如果此处是金币
setTimeout(function() {
$(Sk.TurtleGraphics.target).find('#coin'+y+x).remove()
}, actor.stepSpeed * 3)
map[y][x]=maze.SquareType.OPEN
actor.coin_point+=1
}
}
/**
* 检查精灵在移动的过程中是否走到了标记处
* @param {<number>} x 当前精灵的横坐标.
* @param {<number>} y 当前精灵的纵坐标.
*/
var hasMarker=function(x , y) {
if((map[y][x]==maze.SquareType.MARKER1)||(map[y][x]==maze.SquareType.MARKER2)||(map[y][x]==maze.SquareType.MARKER3)||(map[y][x]==maze.SquareType.MARKER4)){//如果此处是标记
actor.marker_num+=1
}
}
/**
* 检查精灵在移动的过程中是否走到不可见的标记点INVIMAKER
* @param {<number>} x 当前精灵的横坐标.
* @param {<number>} y 当前精灵的纵坐标.
*/
var hasInviMarker=function(x , y) {
if(map[y][x]==maze.SquareType.INVIMAKER){//如果此处是标记
actor.invisible_mark+=1
}
}
//高亮辅助函数
var highlight = function(id) {
id=Sk.ffi.remapToJs(id)
Mixly.Editor.blockEditor.highlightBlock(id);
};
/**
* 设置地图属性.
*
* @param {number} M_x为地图横向方格的数目范围为3-10,初始默认为8
* @param {number} M_y为地图竖向方格的数目范围为3-10,初始默认为8
* @param {string} startPos X, Y 起点位置的坐标.
* @param {string} endPos X, Y 终点位置的坐标
* @param {string} bg_pic为地图背景的图片
*/
var setMap_f=function( M_x , M_y , startPos , endPos , bg_pic) {
Sk.builtin.pyCheckArgs("setMap", arguments, 5, 5);
map=[]
if(bg_pic=='无可用地图'){
bg_pic=""
}
if((M_x<3) || (M_x>20) || (M_y<3) || (M_y>20)){
throw new Sk.builtin.TypeError("错误超出地图可设置范围请设置横纵方格数大于等于3小于等于20");
}
M_x = Sk.ffi.remapToJs(M_x);
M_y = Sk.ffi.remapToJs(M_y);
maze_COLS=M_x;
maze_ROWS=M_y;
maze.MAZE_WIDTH= maze_SQUARE_SIZE * maze_COLS;
maze.MAZE_HEIGHT=maze_SQUARE_SIZE * maze_ROWS;
startPos =Sk.ffi.remapToJs(startPos)
endPos =Sk.ffi.remapToJs(endPos)
switch (Sk.ffi.remapToJs(bg_pic)){
case "bg_default":
maze.background ='../common/js/skulpt_mixcar/pic/bg_default.png';//默认为方格
break;
case "bg_astro":
maze.background ='../common/js/skulpt_mixcar/pic/bg_astro.jpg';//设置为管道
break;
case "bg_panda":
maze.background ='../common/js/skulpt_mixcar/pic/bg_panda.jpg';//设置为竹子
break;
}
var re=/\((\d+),(\d+)\)/.exec(startPos);
if(re!=null){
if((re[1]>M_x) || (re[1]<1) || (re[2]>M_y) || (re[2]<1)){
throw new Sk.builtin.TypeError("错误!起点坐标超出地图范围!");
}
}
var re=/\((\d+),(\d+)\)/.exec(endPos);
if(re!=null){
if((re[1]>M_x) || (re[1]<1) || (re[2]>M_y) || (re[2]<1)){
throw new Sk.builtin.TypeError("错误!终点坐标超出地图范围!");
}
}
for (var i=0; i<M_y; i++){
var b = []; //辅助数组
for(var j=0; j<M_x; j++){
var pos='('+(j+1)+','+(i+1)+')'
if( pos==startPos){
b[j]=maze.SquareType.START;
}else if(pos==endPos){
b[j]=maze.SquareType.FINISH;
}else{
b[j]=maze.SquareType.OPEN;
}
}
map[i]=b;
}
}
mod.setMap = new Sk.builtin.func(setMap_f);
/**
* 设置路径类型,如果不对路径形状进行设置,则默认为方格.
*
* @param {string} path_type代表可通行路径的样式默认为null
*/
var setPathType_f=function(path_type) {
Sk.builtin.pyCheckArgs("setPathType", arguments, 1, 1);
path_type = Sk.ffi.remapToJs(path_type);
switch (path_type){
case "default":
maze.tiles='../common/js/skulpt_mixcar/pic/maze_path.png';//默认为方格
break;
case "pipeline":
maze.tiles='../common/js/skulpt_mixcar/pic/tiles_astro.png';//设置为管道
break;
case "bamboo":
maze.tiles='../common/js/skulpt_mixcar/pic/tiles_panda.png';//设置为竹子
break;
}
}
mod.setPathType = new Sk.builtin.func(setPathType_f);
/**
* 在某处放置障碍或者金币.
*
* @param {number} Pos_x 放置物的x坐标位置.
* @param {number} Pos_y 放置物的y坐标位置.
* @param {string} type 放置物的类型:障碍或是金币
*/
var placeItem_f=function(Pos_x , Pos_y , type) {
Sk.builtin.pyCheckArgs("placeItem", arguments, 3, 3);
Pos_x = Sk.ffi.remapToJs(Pos_x);
Pos_y = Sk.ffi.remapToJs(Pos_y);
type=Sk.ffi.remapToJs(type);
if((map[Pos_y-1][Pos_x-1]==2)||(map[Pos_y-1][Pos_x-1]==3)){
throw new Sk.builtin.TypeError("错误!不能将放置物位置设置在起点或终点坐标!");
}else if((Pos_x>(map[0].length)) || (Pos_x< 0) || (Pos_y>(map.length)) || (Pos_y< 0)){
throw new Sk.builtin.TypeError("错误!放置物坐标超过地图范围");
}
switch(type){
case "wall"://墙:障碍
map[Pos_y-1][Pos_x-1]=maze.SquareType.WALL;
break;
case "coin":
map[Pos_y-1][Pos_x-1]=maze.SquareType.AWARD;
break;
}
}
mod.placeItem = new Sk.builtin.func(placeItem_f);
/**
* 初始化地图
*/
var initMap_f=function() {
drawMap()
}
mod.initMap = new Sk.builtin.func(initMap_f);
var isDone = function(block_id) {
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id)
var isdone= Sk.ffi.remapToPy(checkFinish());
resolve(isdone);
}, 800);
})
}
var isPathCheck=function(direction,block_id) {
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var state="";
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id);
switch (direction) {
case 'left':
direction= 3
state=isPath(direction, null)
break;
case 'right':
direction= 1
state=isPath(direction, null)
break;
};
resolve(Sk.ffi.remapToPy(state));
}, 800);
})
}
var isBarrierCheck=function(direction,block_id) {
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var state=false;
var square=0;
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id);
switch (direction) {
case DirectionType.NORTH:
if(map[actor.y - 1]){
square = map[actor.y - 1][actor.x];
}else{
square = 0
}
break;
case DirectionType.EAST:
if(map[actor.y][actor.x + 1]){
square = map[actor.y][actor.x + 1];
}else{
square = 0
}
break;
case DirectionType.SOUTH:
if(map[actor.y + 1]){
square = map[actor.y + 1][actor.x];
}else{
square = 0
}
break;
case DirectionType.WEST:
if(map[actor.y][actor.x - 1]){
square = map[actor.y][actor.x - 1];
}else{
square = 0
}
break;
};
state= square == maze.SquareType.BARRIER;
resolve(Sk.ffi.remapToPy(state));
}, 800);
})
}
var isOilFullCheck=function(block_id) {
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var state=false;
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id);
if(actor.oil==0){//没油了返回需要加油为True
resolve(Sk.ffi.remapToPy(true));
}else if(actor.oil==1){//还有油返回需要加油为False
resolve(Sk.ffi.remapToPy(false));
}
}, 800);
})
}
var getpoint= function(block_id){
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id)
var point= actor.coin_point;
resolve(Sk.ffi.remapToPy(point));
}, 800);
})
}
var checkLightGreen=function(block_id){
return new Promise((resolve) => {
// Do things
setTimeout( () => {
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
highlight(block_id)
if(actor.traffic_light==maze.SquareType.LIGHT_GREEN){//绿灯,返回 true
resolve(Sk.ffi.remapToPy(true));
}else if(actor.traffic_light==maze.SquareType.LIGHT_RED){//红灯返回false
resolve(Sk.ffi.remapToPy(false));
}
}, 800);
})
}
mod.Actor = Sk.misceval.buildClass(mod, function($gbl, $loc) {
$loc.__init__ = new Sk.builtin.func(function(self,img , direction ,block_id) {
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
img= Sk.ffi.remapToJs(img) || 'pegman';
if(img=='无可用角色'){
img='pegman';
}
switch (img){
case "pegman":
actor.img='../common/js/skulpt_mixcar/pic/pegman.png';//默认为方格
actor.type="animate"
break;
case "panda":
actor.img='../common/js/skulpt_mixcar/pic/panda.png';//设置为管道
actor.type="animate"
break;
case "astro":
actor.img='../common/js/skulpt_mixcar/pic/astro.png';//设置为竹子
actor.type="animate"
break;
case "robot":
actor.img='../common/js/skulpt_mixcar/pic/robot.png';//设置为机器人
actor.type="still"
break;
case "car":
actor.img='../common/js/skulpt_mixcar/pic/actor_car3.png';//设置为小车
actor.type="animate"
break;
}
actor.direction = Sk.ffi.remapToJs(direction) || DirectionType.NORTH;
size=[52,49]//[height,width]//size需要根据方格的数目来确定
actor.coin_point=0
//高亮效果
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
initPegman()
resolve(Sk.builtin.none.none$);
}, 800);
}));
});
//向某个方向移动移动
//暂时只实现了移动一步
//func: Actor.moveDirection()
$loc.moveDirection=new Sk.builtin.func(function(self,direction,block_id) {
Sk.builtin.pyCheckArgs("moveDirection", arguments, 3,3);
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
actor.direction = parseInt(Sk.ffi.remapToJs(direction));
var command= move(direction) //向某个方向移动
if(command==false){
maze.result=ResultType.FAILURE
layer.alert("挑战失败!请修改后重新尝试", { shade: false })
throw new Sk.builtin.TypeError("挑战失败!请修改后重新尝试");
}
if(maze.mlevel==4){//如果是第四关,则需要判断是否需要加油的问题
//如果左侧存在加油站
// if((map[actor.y - 1][actor.x])==maze.SquareType.OIL_STATION||(map[actor.y + 1][actor.x])==maze.SquareType.OIL_STATION||(map[actor.y ][actor.x-1])==maze.SquareType.OIL_STATION||(map[actor.y ][actor.x+1])==maze.SquareType.OIL_STATION){
if((map[actor.y][actor.x-1])==maze.SquareType.OIL_STATION){
if(actor.oil==0){//在加油站处,如果没有油还想继续往前面走
maze.result=ResultType.FAILURE
svg.append('image').attr('id','caroil').attr('x',maze_SQUARE_SIZE).attr('y',3.5 * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/no_oil.png')
layer.alert("挑战失败!小车没有油了", { shade: false })
throw new Sk.builtin.TypeError("挑战失败!小车没有油了");
}
}
}else if(maze.mlevel==5){//如果是第五关,则需要记录循环次数;每次经过起点处循环次数+1
if((map[actor.y][actor.x])==maze.SquareType.START){
actor.circulation_num+=1;
}
}else if(maze.mlevel==7){//如果是第七关,则需要判断红绿灯是否为绿灯的问题
if(actor.traffic_light==maze.SquareType.LIGHT_RED){
layer.alert("挑战失败:小车在红灯亮时还未停止!", { shade: false });
throw new Sk.builtin.TypeError("挑战失败:小车在红灯亮时还未停止!");
}
}
switch (command) {
case 'north':
schedule([actor.x, actor.y, actor.direction * 4],
[actor.x, actor.y - 1, actor.direction * 4]);
actor.y--;
break;
case 'east':
schedule([actor.x, actor.y, actor.direction * 4],
[actor.x + 1, actor.y, actor.direction * 4]);
actor.x++;
break;
case 'south':
schedule([actor.x, actor.y, actor.direction * 4],
[actor.x, actor.y + 1, actor.direction * 4]);
actor.y++;
break;
case 'west':
schedule([actor.x, actor.y, actor.direction * 4],
[actor.x - 1, actor.y, actor.direction * 4]);
actor.x--;
break;
}
//高亮效果
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
hasCoin(actor.x,actor.y)
hasMarker(actor.x,actor.y)
hasInviMarker(actor.x,actor.y)
if(maze.mlevel==7){//如果是第七关,则需要随机改变红绿灯的颜色
if((map[actor.y][actor.x+1])==maze.SquareType.LIGHT_RED || (map[actor.y][actor.x+1])==maze.SquareType.LIGHT_GREEN){
map[actor.y][actor.x+1]=Math.random()>0.5? maze.SquareType.LIGHT_RED:maze.SquareType.LIGHT_GREEN;//随机刷新红绿灯的状态
actor.traffic_light=map[actor.y][actor.x+1];
if(actor.traffic_light==maze.SquareType.LIGHT_RED){//图像变为红灯
const elem = Sk.TurtleGraphics.target.querySelector("#lightgreen");
d3.select(elem).remove();
svg.append('image').attr('id','lightred').attr('x',(actor.x+1) * maze_SQUARE_SIZE-5).attr('y',actor.y * maze_SQUARE_SIZE+5).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/redlight.png')
}
}
}
var state=checkFinish()
if(state=="error2"){
maze.result=ResultType.FAILURE
layer.alert("挑战失败,请检查是否通过所有标记点!", { shade: false })
throw new Sk.builtin.TypeError("挑战失败,请检查是否通过所有标记点!");
}else if(state=="error3"){
layer.alert("挑战失败,请修改后重新尝试!", { shade: false })
throw new Sk.builtin.TypeError("挑战失败!请修改后重新尝试");
}
resolve(Sk.builtin.none.none$);
}, 800);
}));
});
$loc.turn=new Sk.builtin.func(function(self,direction,block_id){
Sk.builtin.pyCheckArgs("turn", arguments, 3, 3);
Sk.builtin.pyCheckType("direction", "string", Sk.builtin.checkString(direction));
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
direction=Sk.ffi.remapToJs(direction)
var command=turn(direction)
switch (command) {
case 'left':
schedule([actor.x, actor.y, actor.direction * 4], [actor.x, actor.y, actor.direction * 4 - 4]);
actor.direction = constrainDirection4(actor.direction - 1);
break;
case 'right':
schedule([actor.x, actor.y, actor.direction * 4], [actor.x, actor.y, actor.direction * 4 + 4]);
actor.direction = constrainDirection4(actor.direction + 1);
break;
}
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
resolve(Sk.builtin.none.none$);
}, 800);
}));
});
$loc.isDone=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("isDone", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(isDone(block_id).then((r) => Sk.ffi.remapToPy(r)));
});
$loc.isPath=new Sk.builtin.func(function(self,direction){
Sk.builtin.pyCheckArgs("isPath", arguments, 2, 2);
Sk.builtin.pyCheckType("direction", "string", Sk.builtin.checkString(direction));
direction=Sk.ffi.remapToJs(direction)
return new Sk.misceval.promiseToSuspension(isPathCheck(direction,block_id).then((r) => Sk.ffi.remapToPy(r)));
});
//判断某个方向是否存在障碍物
$loc.isBarrier=new Sk.builtin.func(function(self,direction,block_id){
Sk.builtin.pyCheckArgs("isBarrier", arguments, 3, 3);
Sk.builtin.pyCheckType("direction", "number", Sk.builtin.checkNumber(direction));
direction=Sk.ffi.remapToJs(direction)
return new Sk.misceval.promiseToSuspension(isBarrierCheck(direction,block_id).then((r) => Sk.ffi.remapToPy(r)));
});
//随机生成小车油量
$loc.randomOil=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("randomOil", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
actor.oil=Math.random()>0.5?1:0;//随机初始化汽车的油量
if(actor.oil==0){//没油(呈现少量油的图片)
svg.append('image').attr('id','caroil').attr('x',maze_SQUARE_SIZE).attr('y',3.5 * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/none_oil.png')
}else if(actor.oil==1){//油量充足(呈现油量充足的图片)
svg.append('image').attr('id','caroil').attr('x',maze_SQUARE_SIZE).attr('y',3.5 * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/full_oil.png')
}
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
resolve(Sk.builtin.none.none$);
}, 800);
}));
});
//判断是否需要加油
$loc.isOilFull=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("isOilFull", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(isOilFullCheck(block_id).then((r) => Sk.ffi.remapToPy(r)));
});
//进加油站加油
$loc.addOil=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("addOil", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
svg.append('image').attr('id','caroil').attr('x',maze_SQUARE_SIZE).attr('y',3.5 * maze_SQUARE_SIZE).attr('width',maze_SQUARE_SIZE).attr('height',maze_SQUARE_SIZE)
.attr('xlink:href','../common/js/skulpt_mixcar/pic/full_oil.png')
actor.oil=1//油量充足
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
resolve(Sk.builtin.none.none$);
}, 800);
}));
});
//获取角色当前的分数
$loc.getPoint=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("getPoint", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(getpoint(block_id).then((r) => Sk.ffi.remapToPy(r)));
});
//判断信号灯是否为绿灯?
$loc.isLightGreen=new Sk.builtin.func(function(self,block_id){
Sk.builtin.pyCheckArgs("isLightGreen", arguments, 2, 2);
return new Sk.misceval.promiseToSuspension(checkLightGreen(block_id).then((r) => Sk.ffi.remapToPy(r)));
});
//检查循环的次数是否正确
$loc.isCirculationRight=new Sk.builtin.func(function(self){
Sk.builtin.pyCheckArgs("isCirculationRight", arguments, 1, 1);
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
var mlevel=maze.mlevel;//获取当前关卡序数
var state=false;
switch (mlevel){
case 5://第五关
state=actor.circulation_num==3?true:false;
break;
case 7://第七关
if(actor.traffic_light==maze.SquareType.LIGHT_GREEN){//如果是绿灯,则怎么都算失败
state=false;
}else if(actor.traffic_light==maze.SquareType.LIGHT_RED){//如果是红灯
for (var y = 0; y < maze.map.length; y++) {
for (var x = 0; x < maze.map[0].length; x++) {
if(maze.map[y][x]==maze.SquareType.LIGHT_RED){
if((actor.x+1)==x|| (actor.y)==y){//如果小车停的位置在红绿灯的左边,则挑战成功
state=true;
}
}
}
}
}
break;
}
if(state==false){
maze.result=ResultType.FAILURE
layer.alert("挑战失败,请检查循环次数是否正确!", { shade: false })
throw new Sk.builtin.TypeError("挑战失败,请检查循环次数是否正确!");
}else{
maze.result=ResultType.SUCCESS
resolve(Sk.builtin.none.none$);
}
}, 800);
}))
});
//检查是否挑战成功
$loc.isSuccess=new Sk.builtin.func(function(self){
Sk.builtin.pyCheckArgs("isSuccess", arguments, 1,1);
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
var state=checkFinish()
if(state==true){
setTimeout(function() {
layer.alert("挑战成功!", { shade: false });
},1000)
resolve(Sk.builtin.none.none$);
}else if(state==false){//没有到达终点就游戏结束,或者超过了终点
maze.result=ResultType.FAILURE
layer.alert("挑战失败,请检查是否到达终点!", { shade: false })
throw new Sk.builtin.TypeError("挑战失败,请检查是否到达终点!");
}
}))
})
}, "Actor")
/**
* 初始化为设定好的地图
*
* @param {number} level 初始化地图level为地图的等级.
* @param {string} block_id 图形块ID.
*/
var settedMap_f=function(level,block_id) {
return new Sk.misceval.promiseToSuspension(new Promise(function(resolve) {
Sk.setTimeout(function() {
//高亮效果
var re=/block_id=([\s\S]*)/.exec(block_id)
if(re!=null){
block_id=re[1];
highlight(block_id)
}
level=Sk.ffi.remapToJs(level)
maze=MAZE_setted[level]
map=MAZE_setted[level].map
drawMap()
resolve(Sk.builtin.none.none$);
}, 800);
}));
}
mod.settedMap = new Sk.builtin.func(settedMap_f);
return mod;
}