简体   繁体   English

试图在画布上画一个精灵,但我错过了一些东西

[英]trying to draw a sprite onto canvas but I am missing something

 window.onload = function(){ theVideo(); playVideo(); Move(); Draw(); }; let objectInfo = { canvas: null, context: null, // Number of sprites numberOfFrames: 16, image: null, imageWidth: 128, imageHeight: 192, frameIndex: 0, frameWidth: 0, // Animation interval (ms) msInterval: 1000, x: 10, y: 10, }; const imageFile = "shaggy.png"; function Draw(){ objectInfo.context.drawImage(myImage, shift, 0, frameWidth, frameHeight, 120, 25, frameWidth, frameHeight); } //image setup window.onload= function () { // Canvas setup objectInfo.canvas = document.querySelector("#myCanvas"); objectInfo.context = objectInfo.canvas.getContext("2d"); // Image setup objectInfo.image = new Image(); objectInfo.image.onload = function() { // The this object refers to image because within image onload event handler objectInfo.imageWidth = this.width; objectInfo.imageHeight = this.height; // Calculate framewidth (size of each sprite) objectInfo.frameWidth = objectInfo.imageWidth / objectInfo.numberOfFrames; }; // Load image objectInfo.image.src = imageFile; }; var xPos = 0; var yPos = 0; //move image function Move(e){ //right if(e.keyCode==39){ xPos+=5; } //left if(e.keyCode==37){ xPos-=5; } //up if(e.keyCode==38){ yPos-=5; } //down if(e.keyCode==40){ yPos+=5; } } 
 <!DOCTYPE html> <html lang="en"> <head> <title>Sprite</title> <meta charset="utf-8"> <meta name="author" content="Peyton"> <meta name="description" content="115"> <link rel= 'stylesheet' href="p4.css"> <script src="p4.js"> </script> <style>canvas { border: 1px solid black; }</style> <body> <canvas width= "1300" height= "600" id= "myCanvas"> <video id="video" controls > <source src="ScoobyDooV.mp4"/> <source src="ScoobyDooV.ogv"/> </video> </canvas> </body> </html> <nav> </nav> <main id="#wrapper"><br> </main> </body> </html> 

I'm really new to coding and am not sure what I am missing to call my sprite and draw the first image onto the canvas. 我是编码的新手,不确定将Sprite并将第一个图像绘制到画布上时会丢失什么。 I later have to call each measurement of my sprite and assign to a function keydown event to make it look like its walking each direction so if I could get any guidance on that too that would be great. 后来我不得不调用我的精灵的每个度量值,并分配给一个函数keydown事件,以使其看起来像在朝每个方向移动,因此,如果我也能对此获得任何指导,那将是很棒的。

在此处输入图片说明

It looks like you're calling Draw before the image is loaded. 看起来您在加载图像之前正在调用Draw。 Try placing the Draw() call within the image.onload method. 尝试将Draw()调用放置在image.onload方法中。

您将window.onload定义了两次,因此仅执行两个回调中的一个

Your code is completely not suited to the task you are attempting. 您的代码完全不适合您要尝试的任务。 Animations require regular rendering. 动画需要定期渲染。 There is a huge amount of missing code in your example so i can really solve any problems directly. 您的示例中有大量缺少的代码,因此我真的可以直接解决任何问题。

So just thought I would give an example of how to load, animate, and render sprites sheets. 因此,以为我会举一个有关如何加载,设置动画和渲染精灵表的示例。

Sprite sheets 雪碧表

There are many ways to handle sprite sheets, though I find that using a standard method for all sprite sheets makes life easy. 有多种处理Sprite表格的方法,尽管我发现对所有Sprite表格使用标准方法都使生活变得轻松。

Some sprite sheets have a regular layout and evenly spaced sprites, other sprite sheets, have been packed together to conserve pixels and memory. 一些子画面具有规则的布局,并且等距的子画面已被均匀地排列在一起,以节省像素和内存。

Each sprite has a location on the sheet, the top left corner and the size as width and height. 每个子画面在图纸上都有一个位置,左上角,其大小为宽度和高度。

You can attach an array of these locations to an image 您可以将这些位置的数组附加到图像上

For example the next function creates sprites for a regular layout (like image in your question) 例如,下一个函数为常规布局创建子画面(例如您问题中的图像)

function createSprites(width, height, columns, rows, image) {
  const sprites = [];
  var w = width / columns;
  var h = height / rows;
  var ix, iy;
  for (iy = 0; iy < rows; iy++) {
    for (ix = 0; ix < columns; ix++) {
      const x = ix * w;
      const y = iy * h;
      sprites.push({ x, y, w, h });
    }
  }
  image.sprites = sprites;
}

The array is added to the img so you don't have to add additional management 该数组已添加到img,因此您无需添加其他管理

You can then draw the sprite by creating a custom draw function. 然后,您可以通过创建自定义绘制函数来绘制精灵。

function drawSprite(img, sprIndex, x, y) {
  const spr = img.sprites[sprIndex];
  ctx.drawImage(img,
    spr.x, spr.y, spr.w, spr.h, // location on sprite sheet
    x , y  ,       // location on canvas
    spr.w, spr.h, // size on canvas;
  );

}

You pass the sprite sheet image, the sprite index in the sprite array, and the location you want to draw the sprite. 您传递Sprite表图像,Sprite数组中的Sprite索引以及要绘制Sprite的位置。

Easy as 容易

Because you likely know the size of the sprite sheet, and the location of the sprites you don't have to wait for the image to load to attach the sprite data. 因为您可能知道Sprite工作表的大小以及Sprite的位置,所以不必等待图像加载即可附加Sprite数据。

 const ctx = canvas.getContext("2d"); const spriteSheet = new Image; spriteSheet.src = "https://i.stack.imgur.com/hOrC1.png"; // The image size is known so you dont have to wait for it to load createSprites(128, 192, 4, 4, spriteSheet); // add a array of sprite locations // It is important that the sprite sizes are integers // width must be divisible by columns and height by rows function createSprites(width, height, columns, rows, image) { const sprites = []; var w = width / columns; var h = height / rows; var ix, iy; for (iy = 0; iy < rows; iy++) { for (ix = 0; ix < columns; ix++) { const x = ix * w; const y = iy * h; sprites.push({ x, y, w, h }); } } image.sprites = sprites; } function drawSprite(img, sprIndex, x, y) { const spr = img.sprites[sprIndex]; ctx.drawImage(img, spr.x, spr.y, spr.w, spr.h, // location on sprite sheet x , y , // location on canvas spr.w, spr.h, // size on canvas; ); } const walkerInfo = { framesPerDir: 4, movements: [{x: 0,y: 3 },{ x: -5, y: 0 }, { x: 5, y: 0 }, { x: 0, y: -3 } ], } const walker = { dir: 0, // 0,1,2,3 time: 0, // time in Frames rate: 0, // steps per frame x: 0, // position y: 0, // update() { this.time += 1; // only move when sprite frame changes if ((this.time % this.rate) === 0) { this.x += walkerInfo.movements[this.dir].x; this.y += walkerInfo.movements[this.dir].y; if(this.x < -128 || this.x > canvas.width || this.y < -192 || this.y > canvas.height) { this.x = randI(canvas.width); this.y = randI(canvas.height); this.dir = randI(4) this.rate = randI(6, 12) } } if(randI(1000) === 0){ this.dir = (this.dir + (randI(2) ? 2 : 1)) % 4; this.rate = randI(6, 12) } }, draw() { var index = this.dir * walkerInfo.framesPerDir; index += (this.time / this.rate | 0) % walkerInfo.framesPerDir; drawSprite( spriteSheet, index, this.x, this.y ); } } function createWalker(x = randI(w), y = randI(h), dir = randI(4), rate = randI(6, 18)) { return { ...walker, x, y, dir, rate, time: randI(100) }; } const walkers = []; // main update function function update(timer) { globalTime = timer; ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform ctx.globalAlpha = 1; // reset alpha if (w !== innerWidth || h !== innerHeight) { cw = (w = canvas.width = innerWidth) / 2; ch = (h = canvas.height = innerHeight) / 2; } else { ctx.clearRect(0, 0, w, h); } if (spriteSheet.complete) { // has the image loaded if (randI(walkers.length) === 0) { // odd 1/100 to create a walker walkers.push(createWalker()); } walkers.sort((a,b)=>ay - by); eachOf(walkers, walk => walk.update()); eachOf(walkers, walk => walk.draw()); } requestAnimationFrame(update); } requestAnimationFrame(update); var w = canvas.width; var h = canvas.height; var cw = w / 2; // center var ch = h / 2; var globalTime; const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0; const rand = (min = 1, max = min + (min = 0)) => Math.random() * (max - min) + min; const eachOf = (array, cb) => { var i = 0; const len = array.length; while (i < len && cb(array[i], i++, len) !== true); }; 
 canvas { position: absolute; top: 0px; left: 0px; } 
 <canvas id="canvas"></canvas> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM