Javascript 函数绘制混合特性
我正在尝试创建一个2d平台,代码是它的基础 由于一些未知的原因,我的最终函数图混合了其他函数的属性(特别是颜色和线宽等) 如果存在类型原因(“此.”功能不合适等) 我想知道更多的项目 任何好的回答都将不胜感激Javascript 函数绘制混合特性,javascript,css,html,html5-canvas,Javascript,Css,Html,Html5 Canvas,我正在尝试创建一个2d平台,代码是它的基础 由于一些未知的原因,我的最终函数图混合了其他函数的属性(特别是颜色和线宽等) 如果存在类型原因(“此.”功能不合适等) 我想知道更多的项目 任何好的回答都将不胜感激 /*main.js*/ var canvas=document.getElementById(“canvas”); var ctx=canvas.getContext(“2d”) 函数Shooter(){ 这是x=100; 这个y=500; 这个尺寸=50; this.color=“蓝色
/*main.js*/
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”)
函数Shooter(){
这是x=100;
这个y=500;
这个尺寸=50;
this.color=“蓝色”;
this.borderColor=“黑色”;
这是一个宽度为5;
this.draw=函数(){
ctx.fillRect(this.x,this.y,this.size,this.size);
ctx.strokeRect(this.x,this.y,this.size,this.size);
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
}
}
功能枪(){
这个.x=sh.x+sh.size/2+10;
这个.y=sh.y+sh.size/2;
此参数为:color=“grey”;
this.borderColor=“brown”;
此值为1.borderWidth=1;
这个宽度=20;
这个高度=10;
this.draw=函数(){
ctx.fillRect(this.x,this.y,this.width,this.height);
ctx.strokeRect(这个.x,这个.y,这个.宽度,这个.高度);
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
}
}
函数Bullet(){
这个.x=sh.x+sh.size*2;
这个.y=sh.y+sh.size/2;
this.color=“橙色”;
这个半径=5;
这是1.vx=20;
this.borderColor=“绿色”;
此值为0.borderWidth=2;
this.draw=函数(){
弧(这个.x,这个.y,这个.radius,0,2*Math.PI);
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
ctx.stroke();
}
}
var sh=新射手();
var g=新枪();
var b=新项目符号();
函数绘图(){
sh.draw();
g、 draw();
b、 draw();
请求动画帧(绘制);
}
draw()代码>
/*main.css*/
html,正文{
溢出:隐藏;
}
页面标题
问题在于首先绘制形状,然后设置填充和笔划。这样可以为下一个形状设置填充和笔划
在我的代码中,我使用了ctx.translate(0,-400)
,因为否则画布会太大。设置画布大小时删除此行
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
//设置画布大小
画布宽度=400;
画布高度=200;
ctx.translate(0,-400);
函数Shooter(){
这是x=100;
这个y=500;
这个尺寸=50;
this.color=“蓝色”;
this.borderColor=“黑色”;
这是一个宽度为5;
this.draw=函数(){
//首先设置此形状的颜色
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
//然后填充并划过形状
ctx.fillRect(this.x,this.y,this.size,this.size);
ctx.strokeRect(this.x,this.y,this.size,this.size);
}
}
功能枪(){
这个.x=sh.x+sh.size/2+10;
这个.y=sh.y+sh.size/2;
此参数为:color=“grey”;
this.borderColor=“brown”;
此值为1.borderWidth=1;
这个宽度=20;
这个高度=10;
this.draw=函数(){
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
ctx.fillRect(this.x,this.y,this.width,this.height);ctx.strokeRect(this.x,this.y,this.width,this.height);
}
}
函数Bullet(){
这个.x=sh.x+sh.size*2;
这个.y=sh.y+sh.size/2;
this.color=“橙色”;
这个半径=5;
这是1.vx=20;
this.borderColor=“绿色”;
此值为0.borderWidth=2;
this.draw=函数(){
ctx.beginPath();
弧(这个.x,这个.y,这个.radius,0,2*Math.PI);
ctx.fillStyle=this.color;
ctx.strokeStyle=this.borderColor;
ctx.lineWidth=此.borderWidth;
ctx.fill();
ctx.stroke();
}
}
var sh=新射手();
var g=新枪();
var b=新项目符号();
函数绘图(){
sh.draw();
g、 draw();
b、 draw();
请求动画帧(绘制);
}
draw()代码>
canvas{border:1px solid}
一些额外的要点。
现有版本将解决您的问题,但是我有一些时间,并注意到您的代码中有一些可以改进的地方
表演为王
在编写游戏(或为此制作内容动画)时,您将看到动画的复杂性(动画和绘制项目的数量)达到某个阶段,设备无法再以全帧速运行。当您尝试覆盖更大范围的设备时,这将成为更大的问题
要在Javascript中获得每行代码的最高速度,您需要了解有关对象的一些简单规则,以及它们是如何创建和销毁的(为其他对象释放内存)
JavaScript是可管理的
这意味着作为一个程序员,你不需要担心内存。您创建了一个对象,并为您找到了该对象的内存。当您不再需要对象时,javascript将清理内存,以便其他对象可以自由使用
这使得用Javascript编程更容易。但是,在动画中,这可能会成为一个问题,因为管理内存分配和清理(也称为删除分配的内存或GC垃圾收集)的代码需要时间。如果动画需要很长时间来计算和渲染每个帧,则GC将强制阻止脚本并进行清理
这种内存管理是Javascript动画(游戏)中最大的Jank来源
它还引入了创建对象的额外处理,因为在创建新对象时必须定位和分配空闲内存。信息技术
function Shooter() {
// Use closure to define the properties of the object
var x = 100;
var y = 500;
const size = 50;
const style = {
fillStyle : "blue",
strokeStyle : "black",
lineWidth : 5,
}
// the interface object defines functions and properties that
// need to be accessed from outside this function
const API = {
draw() {
ctx.fillStyle = style.fillStyle;
ctx.strokeStyle = style.strokeStyle;
ctx.lineWidth = style.lineWidth;
ctx.fillRect(x, y, size, size);
ctx.strokeRect(x, y, size, size);
// it is quicker to do the above two lines as
/*
ctx.beginPath(); // this function is done automatically
// for fillRect and strokeRect. It
ctx.rect(x, y, size, size);
ctx.fill();
ctx.stroke();
*/
}
}
return API;
}
const player = new Shooter();
// or
const player = Shooter(); / You dont need the new for this type of object
// to draw
player.draw();
const bullets = (() => { // a singleton
function Bullet() { }
const radius = 5;
const startLife = 100;
this.radius = 5;
const style = {
fillStyle : "orange",
strokeStyle : "green",
lineWidth : 2,
}
// to hold the interface
Bullets.prototype = {
init(x,y,dx,dy) { // dx,dy are delta
this.life = startLife;
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
},
draw() {
ctx.arc(this.x, this.y, radius, 0 , Math.PI * 2);
},
move() {
this.x += this.dx;
this.y += this.dy;
this.life --;
}
};
const pool = []; // holds unused bullets
const bullets = []; // holds active bullets
// The API that manages the bullets
const API = {
fire(x,y,dx,dy) {
var b;
if(pool.length) {
b = bullets.pop();
} else {
b = new Bullet();
}
b.init(x,y,dx,dy);
bullets.push(bullets); // put on active array
},
update() {
var i;
for(i = 0; i < bullets.length; i ++) {
const b = bullets[i];
b.move();
if(b.life <= 0) { // is the bullet is no longer needed move to the pool
pool.push(bullets.splice(i--, 1)[0]);
}
}
},
draw() {
ctx.lineWidth = style.lineWidth;
ctx.fillStyle = style.fillStyle;
ctx.strokeStyle = style.strokeStyle;
ctx.beginPath();
for(const b of bullets) { b.draw() }
ctx.fill();
ctx.stroke();
},
get count() { return bullets.length }, // get the number of active
clear() { // remove all
pool.push(...bullets); // move all active to the pool;
bullets.length = 0; // empty the array;
},
reset() { // cleans up all memory
pool.length = 0;
bullets.length = 0;
}
};
return API;
})();
// simple example
bullets.fire(gun.x, gun.y, gun.dirX, gun.dirY);
bullets.update(); // update all bullets
if(bullets.count) { // if there are bullets to draw
bullets.draw();
}
bullets.clear(); // remove bullets from previouse play
bullets.clear();
function Gun(player, bullets) {
this.owner = player;
this.bullets = bullets; // the bullet pool to use.
this.x = player.x + player.size / 2 + 10;
this.y = player.y + player.size / 2;
this.width = 20;
this.height = 10;
const style = {
fillStyle : "grey",
strokeStyle : "brown",
lineWidth : 1,
};
}
// Moving the API to the prototype improves memory use and makes creation a little quicker
Gun.prototype = {
update() {
this.x = this.owner.x + this.owner.size / 2 + 10;
this.y = this.owner.y + this.owner.size / 2;
},
draw() {
ctx.lineWidth = this.style.lineWidth;
ctx.fillStyle = this.style.fillStyle;
ctx.strokeStyle = this.style.strokeStyle;
ctx.beginPath();
ctx.rect(this.x,this.y,this.width,this.height);
ctx.fill();
ctx.stroke();
},
shoot() {
this.bullets.fire(this.x, this.y, 10, 0);
},
}