您的位置:首页 > Web前端 > JavaScript

thml5+js 实现简单的2d引擎

2017-05-12 22:03 513 查看
没错,我就是个标题党,被骗进来来了吧。。。





说是个引擎有点夸张,这只是一个小小的小玩意儿。

好了,不 che dan 了。 

开始正文吧:

先上效果,有兴趣才有看下去的动力。


其实效果也一般啦。。碰撞检查还是有点问题,还请大神们指出。

接下来就是代码了,有点长,这代表我没有藏着掖着。。(就你这垃圾玩意还想藏着)

第一个是一个公用的文件,核心功能都在这里面

/* creat by clzmin
2016.07.30
canvas frameWork
*/

/*数据层
T:工具类
P:图形类*/
(function(window){
//////////工具部分 //////
var T={
Vector2:function(x,y){
if(x){
this.x=x;
}else{
this.x=0;
}
if(y){
this.y=y;
}else{
this.y=0;
}
this.Distance=function(otherVec2){
if(otherVec2 instanceof T.Vector2){
return Math.sqrt((this.x-otherVec2.x)*(this.x-otherVec2.x)+(this.y-otherVec2.y)*(this.y-otherVec2.y));
}else{
return -1;
}
}
this.MultiDistance=function(otherVec2){
if(otherVec2 instanceof T.Vector2){
return (this.x-otherVec2.x)*(this.x-otherVec2.x)+(this.y-otherVec2.y)*(this.y-otherVec2.y);
}else{
return -1;
}
}
this.Rotation=function(sin,cos){
var temp=new T.Vector2();
temp.x = this.x * cos - this.y * sin;
temp.y = this.y * cos + this.x * sin;
return temp;
}
}
}
///////// 对象部分 /////
var objcount=0;
var AllObj=new Array();
var CanSeeObj=new Array();
//vanvas类中自己定义的物体类
var P={
//参数顺序: type
SpuerObj:function(){
objcount++;
//初始化值
if(arguments[0])
this.ObjType=arguments[0];
else
this.ObjType="SpuerObj";
this.id=objcount;
this.IsActive=true;
//全局操作
AllObj.push(this);

this.drawSelf=function(){}
this.IsSelf=function(){}
//释放该对象
this.Destroy=function(){
for(var i=0,k=AllObj.length;i<k;i++){
if(AllObj[i].id && AllObj[i].id==this.id){
AllObj[i]=null;
AllObj.splice(i, 1);
break;
}
}
objcount--;
}

},
Line:function(start,end){
P.SpuerObj.call(this,"Line");
if(start instanceof T.Vector2 && end instanceof T.Vector2){
this.start=start;
this.end=end;
}
this.drawSelf=function(canvas){
canvas.drawLine(this.start.x,this.start.y, this.end.x, this.end.y);
}
this.isSelf=function(mousePosition){
if(mousePosition instanceof T.Vector2 ){
var rate=(this.end.y-this.start.y)/(this.end.x-this.start.x);
var mouserate=(mousePosition.y-this.start.y)/(mousePosition.x-this.start.x);
return Math.abs(mouserate-rate)<0.00001?true:false;
}
return false;
}

},
Circle:function(position,reduice){
P.SpuerObj.call(this,"Circle");
if(position && position instanceof T.Vector2 ){
this.position= position;
}else{
this.position= new T.Vector2(0,0);
}
if( reduice){
this.reduice=reduice;
}else{
this.reduice=1;
}
this.drawSelf=function(canvas){
canvas.drawCircle(this.position.x,this.position.y,this.reduice,0,2*Math.PI,true);
}

this.IsSelf=function(mousePosition){
if(mousePosition instanceof T.Vector2 ){
var distancore= Math.pow(this.position.x-mousePosition.x, 2)+ Math.pow(this.position.y-mousePosition.y, 2);
if(distancore>Math.pow(this.reduice,2))return false;
else return true;
}
}
this.CheckColider=function(otherCircle){
if(otherCircle.ObjType=="Circle"){
var reduicedistance=(otherCircle.reduice+this.reduice)*(otherCircle.reduice+this.reduice);
var multidistance = this.position.MultiDistance(otherCircle.position);
if( multidistance!=-1 && multidistance <= reduicedistance) return true;
else return false;
}else{

return false;
}

}
},
Rect:function(position,width,height){
P.SpuerObj.call(this,"Rect");
if(position instanceof T.Vector2)
this.position= position;
this.width=width;
this.height=height;
this.startPosition=new T.Vector2(this.position.x-this.width*0.5,this.position.y+this.height*0.5);
this.drawSelf=function(canvas,self){
canvas.drawRect(this.startPosition.x,this.startPosition.y,this.width,this.height);
}
},
Triangle:function(a,b,c){
P.SpuerObj.call(this,"Triangle");
if(a instanceof T.Vector2 && b instanceof T.Vector2 && c instanceof T.Vector2){
this.a=a;
this.b=b;
this.c=c;
}

this.drawSelf=function(canvas){
canvas.drawLine(this.a.x,this.a.y,this.b.x,this.b.y);
canvas.drawLine(this.b.x,this.b.y,this.c.x,this.c.y);
canvas.drawLine(this.c.x,this.c.y,this.a.x,this.a.y);
}
}
}
window.ObjData={
allObj:AllObj,
CanvasObj:P,
CanvasTool:T
}
})(window);

/*行为层
C:全局配置
*/
(function(window) {
////////// version1.0 /////////
var context;
var canvasElemnet;
var frmaquery= Math.ceil(1000/30);
var C={
width:0,
height:0,
top:0,
left:0
}
function canvas(id) {
return new canvas.prototype.inte(id);
}
canvas.prototype = {

context:context,

Config:C,

inte: function(id) {
if (id && typeof id === "string"&& document.getElementById(id)) {
canvasElemnet = document.getElementById(id);
C.width=canvasElemnet.width;
C.height=canvasElemnet.height;
UpdataTopAndLeft(canvasElemnet);
OnScroll();
if (canvasElemnet.nodeName.toLowerCase()=="canvas") {
context=canvasElemnet.getContext("2d");
}else throw new Error("search canvas is errro");
}else throw new Error("id error");
},

drawLine:function(Sx,Sy,Ex,Ey,width,color,lineCap,lineJoin){
context.beginPath();
context.moveTo(Sx,Sy);
context.lineTo(Ex,Ey);
context.lineWidth=width?width:1;
context.strokeStyle=color?color:"#30E99C";
context.lineCap=lineCap?lineCap:"round";
context.lineJoin=lineJoin?lineJoin:"round";
context.closePath();
context.stroke();
return this;
},

drawCircle:function(x,y,r,sAngle,eAngle,counterclockw
4000
ise,color,width,fill,count,offsetX,offSetY){
context.beginPath();
if(Object.prototype.toString.call(x) === "[object Array]"){
x.forEach( function(element, index) {
context.beginPath();
var tempx=element[0];
var tempy=element[1];
var tempr=element[2];
var tempsAngle=element[3];
var tempeAngle=element[4];
var tempcounterclockwise=element[5];
context.arc(tempx,tempy,tempr,tempsAngle,tempeAngle,tempcounterclockwise);
var tempcolor=element[6]?element[6]:"#30E99C";
context.strokeStyle=tempcolor;
if(element[7]) context.fillStyle=element[7];
context.lineWidth=element[8]?element[8]:1;
context.stroke();
});
return this;
}
if(typeof count ==="number"){
for(var i=0,k=Math.abs(count);i<k;i++){
context.beginPath();
context.arc(x+offsetX*i,y+offSetY*i,r,sAngle,eAngle,counterclockwise);
var tempcolor=color?color:"#30E99C";
context.strokeStyle=tempcolor;
context.lineWidth=width?width:1;
if(fill) context.fillStyle=fill;
context.stroke();
}
}else if(typeof count ==="undefined"){
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
var tempcolor=color?color:"#30E99C";
context.strokeStyle=tempcolor;
context.lineWidth=width?width:1;
if(fill) context.fillStyle=fill;
context.stroke();
}
return this;
},

drawRect:function(x,y,width,height){
context.beginPath();
context.strokeRect(x,y,width,height);
},

RenderObj:function(){
context.clearRect(0,0,C.width,C.height);
var allObj=new Array();
do{
if(typeof arguments[0] =="undefined"){
allObj=ObjData.allObj;
break;
}
if(typeof arguments[0] =="object"){
allObj.push(arguments[0]);
break;
}
if(Object.prototype.toString.call(arguments[0]) === "[object Array]"){
allObj=arguments[0];
break;
}
}while(false);
allObj.forEach(function(obj){
if(obj.IsActive && obj.drawSelf instanceof Function){
obj.drawSelf(canvas.prototype);
}
});
},

GetSelecObj:function(mousePosition){
var allObj=ObjData.allObj;
var selecObjs=new Array();
if(mousePosition instanceof ObjData.CanvasTool.Vector2){
mousePosition.x=mousePosition.x-C.left;
mousePosition.y=mousePosition.y-C.top;
allObj.forEach(function(obj){
if(obj.IsActive && obj.IsSelf instanceof Function){
if(obj.IsSelf(mousePosition)) selecObjs.push(obj);
}
});
}
return selecObjs;
},

StartEvevnt:function(){
var envet=["click","mouseup","mousedown","scroll"];
envet.forEach(function(obj){
AddEvent(obj, canvasElemnet);
});
}
}

canvas.prototype.inte.prototype = canvas.prototype;
window.canvas = canvas;

//补充内容,都以函数形式来写
function UpdataTopAndLeft(canvasElemnet){
var rect=Tools.getBoundingClientRect(canvasElemnet);
C.top=rect.top;
C.left=rect.left;
}

function OnScroll(){
document.addEventListener("scroll", function(event){
event.preventDefault();
UpdataTopAndLeft(canvasElemnet);
});
}

//事件系统
function AddEvent(type, canvasElemnet) {
if (typeof type != "string") return;
type = type.toLowerCase().replace("on", "");
if (window.addEventListener) {
canvasElemnet.addEventListener(type, EventLiten);
}
else {
type = "on" + type;
canvasElemnet.attachEvent(type, EventLiten);
}

function EventLiten(event) {
event.preventDefault();
var obj = canvas.prototype.GetSelecObj(new ObjData.CanvasTool.Vector2(event.clientX, event.clientY));
type = type.replace("on", "");
type = "on" + type;
obj.forEach( function(element, index) {
if (type in element || element.hasOwnProperty(type)) {
if (typeof element[type] === "function") {
element[type].call(this,event);
}
}
});
}
}

})(window);

//工具函数 Tools.方法名
+ function() {
var Tools={
getBoundingClientRect:function(element) {
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
if (element.getBoundingClientRect) {
if (typeof arguments.callee.offset != "number") {
var temp = document.createElement("div");
temp.style.cssText = "position:absolute;top:0px;left:0px;";
document.body.appendChild(temp);
arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;
document.body.removeChild(temp);
temp = null;
}
var rect = element.getBoundingClientRect();
var offset = arguments.callee.offset;
return {
left: rect.left + offset,
right: rect.right + offset,
top: rect.top + offset,
bottom: rect.bottom + offset
}
} else {
var acutaLeft = Tools.getElemntLeft(element);
var acutaTop = Tools.getElementTop(element);
return {
left: acutaLeft - scrollLeft,
right: acutaLeft + element.offsetWidth - scrollLeft,
top: acutaTop - scrollTop,
bottom: acutaTop + element.offsetHeight - scrollTop
}
}
},
getElementTop:function(element){
var actuaTop=element.offsetTop;
var current=element.offsetParent;
while(current!==null){
actuaTop+=current.offsetTop;
current=current.offsetParent;
}
return actuaTop;
},
getElemntLeft:function(element){
var actuaLeft=element.offsetLeft;
var current=element.offsetParent;
while(current!==null){
actuaLeft+=current.offsetLeft;
current=current.offsetParent;
}
return actuaLeft;
}
}
window.Tools=Tools;
}();

下面一个是界面的逻辑文件,画圈圈与碰撞检测都是在这里面完成的。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cnvers</title>
<script src="common/canvas.js"></script>
<style>
.contaner{
width:30px;

}
</style>
</head>
<body height="100%">
<div>
<canvas height="768" width="1024" id="canvas" style=" border: 1px solid red;"> youre browers don't surrpost canvas, please use chorme</canvas>
</div>
</body>
<script>
var frmacout=30;
var frmaquery= Math.ceil(1000/30);
var canva=canvas("canvas");
+function(){
var T=ObjData.CanvasTool;
var P=ObjData.CanvasObj;
var moveCircles=new Array();

function MoveCirCles(speed,position,reduice){
P.Circle.call(this);
moveCircles.push(this);
if(position instanceof T.Vector2){
this.position=position;
}
this.speed=new T.Vector2(0,0);
if(speed instanceof T.Vector2){
this.speed=speed;
}
this.reduice=reduice;
this.Move=function(speed){
if( speed && speed instanceof T.Vector2){
this.position.x+=(speed.x)/frmacout;
this.position.y+=(speed.y)/frmacout;
}else{
this.position.x+=(this.speed.x)/frmacout;
this.position.y+=(this.speed.y)/frmacout;
}
}
}

var creat=setInterval(function(){
var circleone=new MoveCirCles(new T.Vector2(Math.random()*300,Math.random()*300),new T.Vector2(Math.random()*500,Math.random()*500),30);
if(moveCircles.length>30){
clearInterval(creat);
}
},1000);

// var BeziCircles=new Array();

// function BeziCircle( start, beizipos, endpos){
// P.Circle.call(this);
// BeziCircles.push(this);
// this.position=start;
// this.cazhi=0.0;
// this.endpos=endpos;
// this.beizipos=beizipos;

// this.Move=function(){
// this.position.x=(1.0- this.cazhi)*(1.0- this.cazhi)*start.x+2.0*this.cazhi*(1.0- this.cazhi)*beizipos.x+this.cazhi*this.cazhi*endpos.x;
// this.position.y=(1.0- this.cazhi)*(1.0- this.cazhi)*start.y+2.0*this.cazhi*(1.0- this.cazhi)*beizipos.y+this.cazhi*this.cazhi*endpos.y;
// var cicl=new P.Circle(new T.Vector2(this.position.x,this.position.y));
// }
// }
// var bezicir=new BeziCircle(new T.Vector2(100.0,100.0), new T.Vector2(250.0,100.0),new T.Vector2(300.0,300.0));
// var cicl=new P.Circle(new T.Vector2(100,100));
// cicl.reduice=5;
// var cicl=new P.Circle(new T.Vector2(250,100));
// cicl.reduice=5;
// var cicl=new P.Circle(new T.Vector2(300,300));
// cicl.reduice=5;
window.onload=function(){
+function(){
Updata();
Render();
timer=setTimeout(arguments.callee, frmaquery);
}();

function Render(){
canva.RenderObj();
}
function Updata(){
// if(bezicir.cazhi>1){
// bezicir.cazhi=1;
// }else {
// bezicir.Move();
// }
// bezicir.cazhi+=(1.0/300.0);

for (var i = moveCircles.length - 1; i >= 0; i--) {
IsRechFrige(moveCircles[i],canva);
moveCircles[i].Move();
}
for (var i = moveCircles.length - 1; i >= 1; i--) {
for (var j = i - 1; j >= 0; j--) {
if(moveCircles[i].CheckColider(moveCircles[j])){
var reduice=moveCircles[j].position.Distance(moveCircles[i]);
var sin=(moveCircles[j].y-moveCircles[i].y)/reduice;
var cos=(moveCircles[j].x-moveCircles[i].x)/reduice;
var speedi=new T.Vector2(moveCircles[i].speed.x,moveCircles[i].speed.y);
var speedj=new T.Vector2(moveCircles[j].speed.x,moveCircles[j].speed.y);
moveCircles[i].speed.Rotation(sin,cos);
moveCircles[j].speed.Rotation(sin,cos);
moveCircles[i].speed.x=-moveCircles[i].speed.x;
moveCircles[j].speed.x=-moveCircles[j].speed.x;
while(moveCircles[i].CheckColider(moveCircles[j])){
moveCircles[i].Move(-speedi.x,-speedi.y);
moveCircles[j].Move(-speedj.x,-speedj.y);
}
}
}
}
}
}
}();

function IsRechFrige(circle,canvas){
if(circle.position.x-circle.reduice<=0){
circle.speed.x = Math.abs(circle.speed.x);
}
if(circle.position.x+circle.reduice>=canvas.Config.width){
circle.speed.x = -Math.abs(circle.speed.x);
}
if(circle.position.y-circle.reduice<=0){
circle.speed.y = Math.abs(circle.speed.y);
}
if(circle.position.y+circle.reduice>canvas.Config.height){
circle.speed.y = -Math.abs(circle.speed.y);
}
}
</script>
</html>如果不出意外,ctrl + c ,ctrl + v 应该是能运行起来的。 不过实际效果还是要看人品的。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript html js canvas