我需要为我的代码添加一些内容才能使其正常工作
首先,我需要制作用于游戏对象的精灵表的纹理:
//I load all my images into an array I can search from
var imageArray = [];//global variables
var textures = [];//global variables
//and use it after defining onload like this:
imageArray.push(img);
图像全部加载后,我初始化 webgl 的纹理:
for(var i = 0; i < imageArray.length; i++){
initializeTexture(imageArray[i]);
}
function initializeTexture(img){//these images are already loaded into the dom
var tex = renderer.viewportContext.createTexture();
renderer.viewportContext.bindTexture(renderer.viewportContext.TEXTURE_2D, tex);
renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_WRAP_S, renderer.viewportContext.CLAMP_TO_EDGE);
renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_WRAP_T, renderer.viewportContext.CLAMP_TO_EDGE);
renderer.viewportContext.texParameteri(renderer.viewportContext.TEXTURE_2D, renderer.viewportContext.TEXTURE_MIN_FILTER, renderer.viewportContext.LINEAR);
var texture = {
width: img.width,
height: img.height,
texture: tex,
};
renderer.viewportContext.bindTexture(renderer.viewportContext.TEXTURE_2D, tex);
renderer.viewportContext.texImage2D(renderer.viewportContext.TEXTURE_2D, 0, renderer.viewportContext.RGBA, renderer.viewportContext.RGBA, renderer.viewportContext.UNSIGNED_BYTE, img);
textures.push(texture);//array containing one of each spritesheet texture
}
然后我有 Animation 对象,我用它来将 spritesheets 分配给游戏对象:
function Animation(spritesheet,tileSize,tileIds,name = "",playOnce = false){
this.name = name;
this.spritesheet = spritesheet;
this.tileSize = tileSize;
this.tileIds = tileIds;
this.speed = 1;
this.currentTile = 0;
this.playOnce = playOnce;
this.texture;
this.state = "stopped";
this.setAnimationSpeed = function(speed){
this.speed = speed;
}
this.setTextureFromImage = function(img){
this.texture = textures[imageArray.indexOf(img)];//find the spritesheet from array of images which is indexed same as textures array texture[i] = imageArray[i] etc.
}
this.setName = function(name){
this.name = name;
}
this.setLoop = function (loop){
this.loop = loop;
}
this.setSpritesheet = function (spritesheet){
this.spritesheet = spritesheet;
}
this.setState = function(state){
this.state = state;
}
this.getState = function(){
return this.state;
}
this.play = function(){
this.state = "playing";
}
this.stop = function(){
this.state = "stopped";
}
this.nextFrame = function(){
if(this.state == "playing"){
if(typeof this.tileIds[this.currentTile+1] !== "undefined"){
this.currentTile++;
}else{
if(this.playOnce)
this.setState("played");
else
this.currentTile = 0;
}
}
}
this.setTextureFromImage(this.spritesheet);
}
作为优化,我可以使用 imageArray 的索引并在渲染时从原始纹理数组中获取纹理。
我在所有游戏对象中都使用 Animation 对象,如下所示:
this.animations = [
new Animation(this.spritesheet,32,[0,1],"walkDown"),//walkdown
new Animation(this.spritesheet,32,[2,3],"walkRight"),//walkright
new Animation(this.spritesheet,32,[4,5],"walkLeft"),//walkleft
new Animation(this.spritesheet,32,[6,7],"walkUp"),//walkup
]
最后我可以用:
//Renderer
this.viewportContext = this.viewportCanvas.getContext("webgl",{ alpha: false ,premultipliedAlpha: false});
this.render = function(){//render one frame
this.sortLayers();//can do sorting here
this.viewportContext.viewport(0,0,this.viewportContext.canvas.width,
this.viewportContext.canvas.height);
this.viewportContext.clear(this.viewportContext.COLOR_BUFFER_BIT);//clear buffers before rendering
for(var i = 0; i < this.layerArray.length;i++){
if(this.layerArray[i].constructor === Array){
for(var j = 0; j < this.layerArray[i].length;j++){
var object = this.layerArray[i][j];
if(typeof object.currentAnimation !== "undefined"){
var tileId = object.currentAnimation.tileIds[object.currentAnimation.currentTile];
var amountOfBlocksInARow = object.currentAnimation.spritesheet.width/object.currentAnimation.tileSize;
var sourceX = Math.floor(tileId % amountOfBlocksInARow) *object.currentAnimation.tileSize;
var sourceY = Math.floor(tileId / amountOfBlocksInARow) *object.currentAnimation.tileSize;
this.drawImage(object.currentAnimation.texture.texture,
object.currentAnimation.texture.width,
object.currentAnimation.texture.height,
sourceX, sourceY,
object.currentAnimation.tileSize,
object.currentAnimation.tileSize,
object.x,object.y,
object.width,object.height);
}
}
}
}
}
}
this.drawImage = function(tex, texWidth, texHeight,srcX, srcY, srcWidth, srcHeight,dstX, dstY, dstWidth, dstHeight){
if (dstX === undefined) {
dstX = srcX;
srcX = 0;
}
if (dstY === undefined) {
dstY = srcY;
srcY = 0;
}
if (srcWidth === undefined) {
srcWidth = texWidth;
}
if (srcHeight === undefined) {
srcHeight = texHeight;
}
if (dstWidth === undefined) {
dstWidth = srcWidth;
srcWidth = texWidth;
}
if (dstHeight === undefined) {
dstHeight = srcHeight;
srcHeight = texHeight;
}
this.viewportContext.enable(this.viewportContext.BLEND);
this.viewportContext.blendFunc(this.viewportContext.SRC_ALPHA, this.viewportContext.ONE_MINUS_SRC_ALPHA);
this.viewportContext.bindTexture(this.viewportContext.TEXTURE_2D, tex);
this.viewportContext.useProgram(program);
this.viewportContext.bindBuffer(this.viewportContext.ARRAY_BUFFER,positionBuffer);
this.viewportContext.enableVertexAttribArray(positionAttributeLocation);
this.viewportContext.vertexAttribPointer(positionAttributeLocation, 2, this.viewportContext.FLOAT, false, 0, 0);
this.viewportContext.bindBuffer(this.viewportContext.ARRAY_BUFFER, textureCoordinateBuffer);
this.viewportContext.enableVertexAttribArray(textureCoordinateLocation);
this.viewportContext.vertexAttribPointer(textureCoordinateLocation, 2, this.viewportContext.FLOAT, false, 0, 0);
this.matrix = m4.orthographic(0, this.viewportContext.canvas.width, this.viewportContext.canvas.height, 0, -1, 1);
this.matrix = m4.translate(this.matrix,dstX,dstY,0);
this.matrix = m4.scale(this.matrix, dstWidth, dstHeight, 1);
this.viewportContext.uniformMatrix4fv(matrixLocation,false,this.matrix);
var textureMatrix = m4.scaling(1/ texWidth, 1/texHeight, 1);
//scaling
textureMatrix = m4.translate(textureMatrix, srcX, srcY, 0);
textureMatrix = m4.scale(textureMatrix, srcWidth, srcHeight, 1);
this.viewportContext.uniformMatrix4fv(textureMatrixLocation, false, textureMatrix);
this.viewportContext.drawArrays(this.viewportContext.TRIANGLES, 0, 6);
}