Javascript-OOP
好的,我为一个JS游戏写了一些代码。代码本身可以工作,但不是正确的OOP形式。在“敌人”类中,我需要引用“玩家”类中的变量和方法。查看引用变量的“碰撞”方法。请注意,我专门从脚本末尾名为“Player”的新实例“Player”中获取数据。对于OOP,我应该如何在这两个类之间共享信息 谢谢Javascript-OOP,javascript,oop,Javascript,Oop,好的,我为一个JS游戏写了一些代码。代码本身可以工作,但不是正确的OOP形式。在“敌人”类中,我需要引用“玩家”类中的变量和方法。查看引用变量的“碰撞”方法。请注意,我专门从脚本末尾名为“Player”的新实例“Player”中获取数据。对于OOP,我应该如何在这两个类之间共享信息 谢谢 var Player=function(){ 这个.x=15; 这个y=15; }; Player.prototype.reset=函数(){ this.x=200;//重置为此 this.y=320;//重
var Player=function(){
这个.x=15;
这个y=15;
};
Player.prototype.reset=函数(){
this.x=200;//重置为此
this.y=320;//重置为此
};
var=function(){
这个.x=25;
这个y=30;
};
defey.prototype.collision=函数(){
如果javascript函数中的(player.x>=this.x-35&player.x=this.y-30&player.y,则可以使用参数
您的问题的解决方案可能是将Player
的实例传递给方法collision
正如@lvaro Touzón所提到的,一个好的做法是在代码中使用继承,因为敌人
和玩家
现在基本相同
此外,您还可以阅读有关ES6类的内容,这些类使编程更加容易,但是它们仍然依赖于原型继承,这使得它们只是语法上的糖分。如果您想使用OOP,那么这可能会对您有所帮助
添加辅助扩展函数
function extend(current, base) {
for (var key in base) {
if (base.hasOwnProperty(key)) {
current[key] = base[key];
}
}
current.prototype = Object.create(base.prototype);
};
按照@alvaro Touzón的建议创建类Avatar
var Avatar = (function () {
function Avatar (x, y) {
this.x = x;
this.y = y;
}
Avatar.prototype.reset = function() {
return this;
};
Avatar.prototype.collision = function(object) {
if (object.x >= this.x - 35 & object.x <= this.x + 35) { // check column
if (object.y >= this.y - 30 & object.y <= this.y + 30) { // check row
object.reset(); // calls object method "reset"
}
}
};
return Avatar;
}());
创建游戏
var Game = (function () {
Game.prototype.player = new Player(15, 15);
Game.prototype.enemys = [
new Enemy(25, 30),
new Enemy(10, 30),
];
function Game () {
// setup
}
Game.prototype.start = function() {
for (var i = 0; i < array.length; i++){
var enemy = this.enemys[i];
this.player.collision(enemy);
}
return this;
};
return Game;
}());
它的工作原理
你有一组对象-敌人和对象-玩家,他们都有能力计算彼此之间的碰撞,因为共同的祖先。每次你调用游戏的开始都会计算碰撞。我会在游戏中添加setInterval
。开始计算碰撞,但这会使游戏复杂化代码。我不能说你想如何运行你的游戏,但总的来说,为了共享数据,我一直相信创建单例类并在不同的对象中使用它。这样我们也可以更好地处理错误。在js中,没有单例类可以这么说。但你可以始终创建简单的js模块,如下所示:
var abc = (function(){
var abc = "someval"; //private variable
var setAbc = function() {
//some logic
}
var getAbc = function() {
//some logic
}
var publicMethod = function {
//some logic
}
return {
setAbc: setAbc,
getAbc: getAbc,
publicMethod: publicMethod
}
})();
变异/重置玩家与敌人无关。重置到哪个位置与玩家无关。
这些事情应该由游戏在主游戏循环中完成,而碰撞
-方法应该只确定这个元素是否击中了传递的元素
//manages the bounding-Box / Collisions,
//also pretty much everything related to (basic) rendering, like Assets/Image or DOM-Node, ... but since you've not included that in your code, I can't adapt it.
class Element{
constructor(config){
let {x, y, width, height, hitBoxOffsetX, hitBoxOffsetY} = config || {};
this.x = +x || 0;
this.y = +y || 0;
this._hitBoxOffsetX = +hitBoxOffsetX || 0;
this._hitBoxOffsetY = +hitBoxOffsetY || 0;
this.width = +width || 0;
this.height = +height || 0;
}
//bounding box
get left(){ return this.x + this._hitBoxOffsetX }
get right(){ return this.left + this.width }
get top(){ return this.y + this._hitBoxOffsetY }
get bottom(){ return this.top - this.height }
collision(other){
return this.right > other.left && this.left < other.right &&
this.top > other.bottom && this.bottom < other.top;
}
}
//everything that can somehow be hit, extends Element
class Player extends Element {
constructor(){
super({
hitBoxOffsetX: -35, //hitBox starts 35px to the left of this.x
hitBoxOffsetY: -30, //hitBox starts 30px to the top of this.y
width: 70, //width of the hitBox
height: 60 //height of the hitBox
});
}
}
class Enemy extends Element {
constructor(){
//since I have no idea about the dimensions of these Entities
super();
}
}
//and walls, for example
class Wall extends Element {
constructor(x, y, width, height){
super({
x, y,
width: +width || 20,
height: +height || 20
});
}
}
如果你在javascript中使用OOP,一个想法是从玩家那里扩展敌人,或者用一个基数代替两个基数,比如阿凡达,或者任何我想传递的名字都是“玩家”,而不是“玩家”到碰撞方法?不,你应该传递玩家的实例,在你的例子中是Player
,这通常是正确的。我使用一个游戏引擎来构建游戏,它使用HTML5画布和JS。引擎只寻找更新游戏的新功能,这在本文中没有特别提到。引擎寻找“player.prototype.update”和“敌方.prototype.update”,它会根据这两个功能不断更新游戏。
var abc = (function(){
var abc = "someval"; //private variable
var setAbc = function() {
//some logic
}
var getAbc = function() {
//some logic
}
var publicMethod = function {
//some logic
}
return {
setAbc: setAbc,
getAbc: getAbc,
publicMethod: publicMethod
}
})();
//manages the bounding-Box / Collisions,
//also pretty much everything related to (basic) rendering, like Assets/Image or DOM-Node, ... but since you've not included that in your code, I can't adapt it.
class Element{
constructor(config){
let {x, y, width, height, hitBoxOffsetX, hitBoxOffsetY} = config || {};
this.x = +x || 0;
this.y = +y || 0;
this._hitBoxOffsetX = +hitBoxOffsetX || 0;
this._hitBoxOffsetY = +hitBoxOffsetY || 0;
this.width = +width || 0;
this.height = +height || 0;
}
//bounding box
get left(){ return this.x + this._hitBoxOffsetX }
get right(){ return this.left + this.width }
get top(){ return this.y + this._hitBoxOffsetY }
get bottom(){ return this.top - this.height }
collision(other){
return this.right > other.left && this.left < other.right &&
this.top > other.bottom && this.bottom < other.top;
}
}
//everything that can somehow be hit, extends Element
class Player extends Element {
constructor(){
super({
hitBoxOffsetX: -35, //hitBox starts 35px to the left of this.x
hitBoxOffsetY: -30, //hitBox starts 30px to the top of this.y
width: 70, //width of the hitBox
height: 60 //height of the hitBox
});
}
}
class Enemy extends Element {
constructor(){
//since I have no idea about the dimensions of these Entities
super();
}
}
//and walls, for example
class Wall extends Element {
constructor(x, y, width, height){
super({
x, y,
width: +width || 20,
height: +height || 20
});
}
}
update(){
requestAnimationFrame(update);
//move everything
//collision-checks
//if your player has some sort of weapon, maybe you want to first check
//wether it has "killed" some enemies,
//before checking wether an enemy has hit your player.
var hitEnemy = enemies.find(enemy => enemy.collision(player));
//btw. Bullets would also be "enemies"
if(hitEnemy){
//and you probably don't want to
player.x = currentLevel.playerResetPosition.x;
player.y = currentLevel.playerResetPosition.y;
//destroy hitEnemy
//maybe mark the player as blinking/non-hitable for a few seconds?
}
//render everything
}